人気ブログランキング |

[まとめ] 専用アプリ導入すら不要!日常作業を自動化する方法

どーもボキです。

他サイトにはないVBScript活用ノウハウまとめ

    MicrosoftがVBScriptの開発終了をして10年以上たつものの、ボキがかかわる業務現場にはいまだVBSも含めたWindowsの標準機能で排除できるムダが多く残ってしまっている。

    ボキは、人生から不要なムダを取り払い、有意義なムダを楽しみたい
    その一環として、仕事において自分の業務だけでなく、関わる周辺メンバ・業務の効率化も行ってきた。

    このブログでは仕事を通じて得たノウハウのうち、他サイトをググっても得られないものを紹介してきた。また、VBSにこだわってきた理由は、VBSからVBA、つまりExcelを始めとしたMicrosoft officeアプリのマクロ開発へ技術応用できるからだ。
    ブログにて情報配信する限り、これらの記事を体系化・構造化してお見せすることが難しい。
    そのため、このまとめ記事に、VBScript活用ノウハウを一覧化しておく。

他サイトにはないVBScript活用ノウハウ一覧

他サイトにないVBScript活用ツール


一歩踏み込んだVBScript言語仕様


にほんブログ村 IT技術ブログへ
にほんブログ村

第五回プラチナブロガーコンテスト開催!


# by yozda | 2021-01-05 12:12 | プログラミング | Comments(0)

[VBScript] TIniFileクラス:iniファイルの処理をカンタンに

どーもボキです。

ini処理ができれば、設定ファイル処理の2/3はできたも当然。TIniFileクラスならその2/3がカンタンに!

    Windows APIには、iniファイル読み書き関数(GetPrivateProfileString、WritePrivateProfileString)が用意されているものの、
    VBSではこれらのAPIを利用できない(正確には、ひと手間かければWindows APIなどのDLLも利用できる、だが)。

    そのため、VBSでもiniファイルをカンタンに処理できるようにとTIniFileクラスを用意した。
    以前公開していたものを改良し、WriteValue/Write後のファイル保存にも対応させた。

    ちなみに、残りの1/3はレジストリ。これは別途記載する。

サンプルプログラムのダウンロードと使い方


TIniFileクラスの使い方

    以下のサンプルで、TIniFileクラスの基本的な使い方が分かると思う。
    DelphiのTIniFileクラスに合わせて開発したので、Delphi経験者ならすんなりと理解できるハズ。
    なお、DelphiにはDeleteSectionはない(DeleteKeyはあり)、この関数はVBS版オリジナル。

    TListクラスを利用し、iniファイルのセクションごとのループ処理もカンタン。
[VBScript] TIniFileクラス:iniファイルの処理をカンタンに_a0021757_10415197.png
    [VBScript] TIniFileクラス:iniファイルの処理をカンタンに_a0021757_10060117.png
    Execute CreateObject("Scripting.FileSystemObject").OpenTextFile(Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName,"\")) & "vbCommon.vbs").ReadAll()
    '─────────────────────────────────────────────────────────────────────────────
    SetScriptHost("cscript")

    Dim fpth
    fpth = ChangeFileExt(WScript.ScriptFullName, ".ini")

    Dim ini
    Set ini = New TIniFile

    ' iniファイルを読み込み
    dprintf "Load" & vbTab & ini.Load(fpth) ' 指定ファイルを読み込み

    ' Keyをループさせ、Sectionを作成
    Dim i,j,s,sec,key
    For i = 0 To 9
    For j = 0 To 9
    sec = "sec_" & j
    key = "key_" & i
    ini.WriteValue sec, key, j*10 +i
    Next
    Next

    ' iniファイルを保存
    dprintf "Save" & vbTab & ini.Save(fpth) ' 指定ファイルに保存

    Dim slst: Set slst = New TList
    Dim tlst: Set tlst = New TList

    ' セクション名リストを取得
    ini.ReadSections(slst)

    For i = 0 To slst.Count -1
    ' セクション内の全キーを取得
    j = ini.ReadSection(slst(i), tlst)

    s = slst(i)
    sec = s
    For j = 0 To tlst.Count -1
    key = tlst(j)
    s = s & vbTAB & ini.ReadValue(sec, key, "-") ' 指定セクション・キーを読み込む
    Next

    dprintf s
    Next

    ' 指定セクションを削除する
    For i = slst.Count -1 To slst.Count/2 Step -1
    dprintf "DeleteSection(sec_" & i & ")" & vbTab & ini.DeleteSection("sec_" & i)
    Next

    ' 指定キーを削除する
    For i = 0 To slst.Count -1: Do
    If Not ini.SectionExists("sec_" & i) Then Exit Do ' セクションの有無をチェックする

    ' セクション内の全キーを取得
    j = ini.ReadSection(slst(i), tlst)

    sec = slst(i)
    For j = tlst.Count -1 To tlst.Count/2 Step -1
    key = tlst(j)
    ini.DeleteKey sec, key ' 指定キーを削除する
    Next
    Loop Until 1: Next

    For i = 0 To 9
    sec = "sec_" & i
    s = sec
    For j = 0 To 9
    key = "key_" & j
    s = s & vbTAB & ini.ReadValue(sec, key, "-") ' 指定セクション・キーを読み込む
    Next

    dprintf s
    Next

この記事での気付き

    Microsoftは設定情報の記録は、INIファイルでなく、XMLやレジストリへの記載を推奨している。
    しかし、ボキの手の届く範囲の業務インフラは、いまだにINIファイルが利用され続けている。

    それは、設定情報をテキストエディタで確認・修正しやすい、からだろう。

    実際にボキ自身、XMLを使ったことはない。
    それは、上記のようにいまだINIファイル主体のため、XMLを含む他の新技術へ移行させるメリットがなかったからだ。

    ただし、新技術を知らないままでいること、それは良いとは言えない。
    外的要因、たとえばWindows更新により、いつレガシー技術が使えなくなる日がくるか分からないからだ。

    あえてレガシー技術を使い続ける場合、新技術への移行に向けた準備を進めておくことが重要だ。
    INIファイルならば、運用効率の良いセクションとキー構造定義技術を身に付ける・命名ルールを作成しておく。

    そうしておけば、構造化記述に長けたXMLへはスンナリ移行できる。
    これにより、レガシー技術を使いつづけつつ、いつでも新技術へ移行する準備ができている状態となる。

2020/5/10掲載記事の更新
にほんブログ村 IT技術ブログへ
にほんブログ村

今回開発したプログラムソースはコチラ
# by yozda | 2021-01-05 09:43 | プログラミング | Comments(0)

[VBScript] TListクラス:テキストやCSVデータの処理をカンタンに

どーもボキです。

CSV処理ができれば、文字列処理の2/3はできたも当然。TListクラスならその2/3がカンタンに!


サンプルプログラムのダウンロードと使い方


TListクラスの使い方:基本編

    以下のサンプルで、TListクラスの基本的な使い方が分かると思う。
    DelphiのTStringListクラスに合わせて開発したので、Delphi経験者ならすんなりと理解できるハズ。
    [VBScript] TListクラス:テキストやCSVデータの処理をカンタンに_a0021757_15294467.png
    Execute CreateObject("Scripting.FileSystemObject").OpenTextFile(Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName,"\")) & "vbCommon.vbs").ReadAll()
    '─────────────────────────────────────────────────────────────────────────────
    SetScriptHost("cscript")

    Dim fpth
    fpth = ChangeFileExt(WScript.ScriptFullName, "")

    ' TListクラスの準備
    Dim slst: Set slst = New TList

    ' Z → Aを降順に処理
    Dim i
    For i = Asc("Z") To Asc("A") Step -1
    slst.Add Chr(i) ' データを追加
    Next
    dprintf "Save " & vbTab & slst.Save(fpth & "0.csv") ' 指定ファイルで保存


    For i = 0 To 2
    dprintf "--------------------------------------------------------------------"

    dprintf "Load " & vbTab & slst.Load(fpth & i & ".csv") ' 指定ファイルを読み込み
    Select Case i
    Case 1
    dprintf "Sort"
    slst.Sort ' 格納データを昇順ソート
    Case 2
    dprintf "Delete(0)"
    slst.Delete(0) ' 先頭データを削除
    End Select
    dprintf "Count " & vbTab & slst.Count ' データ個数
    dprintf "CommaText" & vbTab & slst.CommaText ' カンマ区切りで取り出す
    dprintf "Item(0) " & vbTab & slst(0) ' 先頭データを取得
    dprintf "IndexOf(""A"")" & vbTab & slst.IndexOf("A") ' Aのインデックスを取得
    dprintf "Save " & vbTab & slst.Save(fpth & i+1 & ".csv") ' 指定ファイルで保存
    Next

    dprintf "--------------------------------------------------------------------"

    s = slst.Text("|") ' 指定した文字で格納データを連結し取得
    dprintf "slst.Text(""|"")" & vbTab & s
    slst.Text("|") = s ' 指定した区切り文字で格納
    dprintf "Count " & vbTab & slst.Count ' データ個数
    dprintf "CommaText" & vbTab & slst.CommaText ' カンマ区切りで取り出す
    dprintf "Item(0) " & vbTab & slst(0) ' 先頭データを取得
    dprintf "--------------------------------------------------------------------"

    ' クリア
    slst.Clear
    dprintf "Clear"
    dprintf "--------------------------------------------------------------------"

    ' Key=Valueデータの処理
    For i = 1 To 5
    slst.Values("Key" & i) = i*100 +i*10 +i ' Kev=Valueを追加
    Next

    dprintf "Count " & vbTab & slst.Count ' データ個数
    dprintf "CommaText" & vbTab & slst.CommaText ' カンマ区切りで取り出す
    dprintf "Item(0) " & vbTab & slst(0) ' 先頭データを取得
    dprintf "Values(""Key3"")" & vbTab & slst.Values("Key3") ' Key3のValueを取得
    dprintf "Save " & vbTab & slst.Save(fpth & "3.csv") ' 指定ファイルで保存
    dprintf "--------------------------------------------------------------------"

TListクラスの使い方:応用編

    TListクラスは、Objectの管理にも対応させた。
    Sortを実行すれば、データの並び替えに合わせ格納させたObjectも並び替える。

    これを用いれば、Objectに値を紐付けて管理できるようになる。
    [VBScript] TListクラス:テキストやCSVデータの処理をカンタンに_a0021757_15425691.png

    Execute CreateObject("Scripting.FileSystemObject").OpenTextFile(Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName,"\")) & "vbCommon.vbs").ReadAll()
    '─────────────────────────────────────────────────────────────────────────────
    SetScriptHost("cscript")

    Dim slst,tlst
    Set slst = New TList

    Dim i,j,s

    ' データの格納後にオブジェクトを格納
    slst.Add 10
    slst.Objects(0) = New TList

    ' データとオブジェクトを同時に格納
    slst.AddObject slst.Count, New TList ' 値とオブジェクトを追加

    ' データ数
    dprintf "Count " & vbTab & slst.Count
    dprintf "--------------------------------------------------------------------"

    For i = 0 To slst.Count -1
    Set tlst = slst.Objects(i)
    For j = 0 To 9
    tlst.Add i*10 +j
    'slst.Objects(i) i*10 +j ' slst.Objectsで直接アクセスしてもOK
    Next
    Next

    ' 途中に挿入
    i = 90
    Set tlst = New TList
    For j = 0 To 9
    tlst.Add i +j
    Next
    dprintf "InsertObject" & vbTab & slst.InsertObject(1, i, tlst) ' 指定インデックスに、値とオブジェクトを挿入
    dprintf "--------------------------------------------------------------------"

    ' データ数
    dprintf "Count " & vbTab & slst.Count
    dprintf "--------------------------------------------------------------------"

    ' 格納データの確認
    For i = 0 To slst.Count -1
    dprintf i
    dprintf "slst(" & i & ") " & vbTab & slst(i)

    Set tlst = slst.Objects(i)
    dprintf "tlst.CommaText" & vbTab & tlst.CommaText
    dprintf ""
    Next
    dprintf "--------------------------------------------------------------------"

    ' 並び替え
    dprintf "Sort " & vbTab & slst.Sort
    dprintf "--------------------------------------------------------------------"

    ' 格納データの確認
    For i = 0 To slst.Count -1
    dprintf i
    dprintf "slst(" & i & ") " & vbTab & slst(i)

    Set tlst = slst.Objects(i)
    dprintf "tlst.CommaText" & vbTab & tlst.CommaText
    dprintf ""
    Next
    dprintf "--------------------------------------------------------------------"


TListクラスの実現技術と注意点

    TListクラスは、以下の「その1」の方法を利用している。
    これにより、Loadでテキストファイルを読み込めば、その行数をCountで取得できる。

    非常に扱いやすいクラスであるものの、大容量テキストファイルには向かない。

    それは、テキストファイルのすべてをメモリに確保する処理となっているからだ。
    大容量テキストファイルの場合は、以下の「その2」の方法で、テキストファイル自体を1行ずつ読み込み、行ごとの処理にTListを充てると良い。

    ちなみにこの考え方は他の開発言語でも同じ

    • その1:テキストファイルを一括で読み込む(行ごとにlines配列に格納される)

      Dim objFS
      Set objFS = CreateObject("Scripting.FileSystemObject")
      Dim file,lines
      Set file = objFS.OpenTextFile(FilePath, 1) ' 1=読み取り専用で開く
      lines = Split(file.ReadAll, vbCrLf, -1, vbTextCompare) ' テキストファイルをすべて読み込み、改行コードで配列化する
      file.Close
    • その2:テキストファイルを1行ずつ読み込む

      Dim objFS
      Set objFS = CreateObject("Scripting.FileSystemObject")
      Dim file
      Set file = objFS.OpenTextFile(FilePath, 1) ' 1=読み取り専用で開く
      Do While Not file.AtEndOfStream ' 末尾までループさせる
      MsgBox file.ReadLine ' 1行読み込む
      Loop
      file.Close

この記事での気付き

    TListクラスは、DelphiのTStringListクラスを真似て開発した。
    これによって「Delphi開発経験者ならばすでにTListの機能を知っている」といってもいいくらいだ。

    なぜ、ここまでDelphiを真似ることにこだわったか?
    それは、ボキの係のメイン開発環境だからだ。

    VBSは社内の全PCで利用できるメリットがあったものの、専用の開発環境がなく取り掛かりにくかった。
    これによって、係のメンバはちょっとした処理であっても、すべてDelphiで開発した。

    これにより、小さなブラックボックス処理が増え続けた。
    そして、何が問題となりどのように対処すればよいか分かっているトラブルであっても、人に依存した対応が必要となっていた。

    この小さなブラックボックスの無限増殖を抑え、係のメンバならだれでも対応できるように、と、
    VBS活用を推奨し、このTListクラスや、エディタのみで実現可能なBreakpointデバッグVBSコード支援とデバッグ環境構築、を展開した。

    これらの工夫で、係にVBS開発が定着し、ちょっとした処理なら担当を固定せず対応が可能となるとともに、
    常にソースが見える状態となりメンバ間でのノウハウ共有が加速、結果的に係全体のスキル向上につなげることができた。

    係で仕事をする以上、一人ひとりの技を可視化して共有化させることで互いに気付きを与え続ける、この仕組みがないと人や係が成長しない。

2020/5/9掲載記事の更新
にほんブログ村 IT技術ブログへ
にほんブログ村

今回開発したプログラムソースはコチラ
# by yozda | 2021-01-04 16:02 | プログラミング | Comments(0)

[VBScript] wsfファイルのメリットとその活用方法

どーもボキです。

複数人で共通のvbsファイルを利用するならば、wsfファイル形式での運用がオススメ


wsfファイルのメリット

  • 一つのwsfファイル内に、複数の独立した機能(Job)を組み込める

    wsfファイルにおける各Jobは完全に独立した関係となっている。
    これにより、一つのwsfファイル内に、独立した機能を複数実装することができない。

    vbsファイルの場合は、完全に独立させた関数実装とするか、個別ファイルとして開発する必要がある。

  • HTTPプロトコル上のスクリプトファイルを利用できる

    <script language="VBScript" src="http://*****/vbCommon.vbs"/>
    対して、インクルード実行ではHTTPプロトコル上のファイルは使えない。

  • 同じフォルダ上のスクリプトはファイル名のみでアクセスできる

    <script language="VBScript" src="vbCommon.vbs"/>
    対して、インクルード実行ではドロップ実行時にファイルフルパス指定が必要。

  • エンコードしたスクリプトを利用できる(ただし、注意点アリ。詳細は以下)

    <script language="VBScript.Encode" src="vbCommon.vbe"/>
    対して、インクルード実行にはエンコードしたスクリプトは使えない。


wsfファイルの注意点

    元スクリプトがすべて動くとは限らない。エンコード対象は最小にとどめよう!

    vbCommon.vbe(エンコード済みスクリプト)では、
    TListクラスTIniFileクラスを利用すると、下図のように「クラスが定義されていません」となる。

    全コメントを削除してエンコードしても解決せず(近い症状)。

    この点は、サポート終了のVBS制約として受け入れ、
    エンコード単位をパスワード記載スクリプトのみといった運用で工夫しよう。
    [VBScript] wsfファイルのメリットとその活用方法_a0021757_10102080.png

サンプルのダウンロードと使い方

    wsfファイルのメリットを生かしたサンプルを作ってみた。

  • ダウンロード

  • 使い方は
    wsfファイルに適当なフォルダ・ファイルをドロップする、だけ。

    1. 親Job(冒頭のJob)は、ドロップされたパスを子job(Job:1)で処理させる。
    2. 親Jobは、「Job:1」の結果をもとに「Job:2」を実行する。

    このように、親子Jobを使い分ければ、一つのwsfファイル内での動作機能の切り分け開発が可能。
    各Jobのスクリプトをhttp参照させれば、ユーザ配布したスクリプトの管理も不要となる(Webサーバのみで管理可能)。

この記事での気付き

    そして、wsfファイルにて可能となる「HTTPプロトコル上のスクリプトの活用」。

    これらを徹底できれば、日頃のムダな処理作業は、迅速・長期にわたって排除できそう。

    具体的には、
    • ハイブリット開発で開発言語・技術ごとのメリットを活かす。
    • 処理系の親子関係を定義し、処理系を分離することで、子の処理の再利用性を高めておく。
    • スクリプト管理先をWEBサーバとすることで、ユーザ配布作業を0化する(HTTPアクセスさせる)。
    といった具合に。

にほんブログ村 IT技術ブログへ
にほんブログ村

今回開発したプログラムソース
タグ:
# by yozda | 2021-01-02 14:08 | プログラミング | Comments(0)

[まとめ] amiiboのドットマリオをダイソーのプチブロックで作る

どーもボキです。


ダイソーのプチブロックが4種類あれば、amiiboのドットマリオを作れる!!

[まとめ] amiiboのドットマリオをダイソーのプチブロックで作る_a0021757_14135731.jpg

必要となるプチブロックシリーズ

    クラシックカラー版

    • ウェディングケーキ×1
    • 新婦×2
    • ライオン×3
    • 消防車×2

    モダンカラー版

    • ウェディングケーキ×1
    • コンゴウインコ×3
    • 新婦×2
    • ブルドッグ×1

2017/10/7 7:14掲載記事の更新


設計図はコチラ
# by yozda | 2021-01-02 09:55 | 物・モノ・もの | Comments(11)

[VBScript] 指定した名前のプロセスを強制終了するツール

どーもボキです。

タスクマネージャーに残ったプロセスを一つひとつ終了させるのは面倒。こういうときは強制終了処理をツール化すればよい。



指定プロセスの強制終了ツールのダウンロードと使い方

  • ダウンロード
  • 使い方は、実行して上図のダイアログにプロセス名を入れる、だけ。

強制終了ツールはVBScriptのみでもプロセス終了は可能。しかし……。

    以下のような処理を組めば、VBScriptのみで任意のプロセスを終了させることもできる。
    けれど、VBScriptのみで実現することにこだわらなくても良い。

    TerminateProcess関数のソース(WbemScripting.SWbemLocator利用版)

      TerminateProcess("iexplore.exe")

      '-------------------------------------------------------------------------------
      ' 指定した名前のプロセスを強制終了する
      '-------------------------------------------------------------------------------
      Sub TerminateProcess(ProcessName)
      Dim Service,QfeSet,Qfe
      Set Service = CreateObject("WbemScripting.SWbemLocator").ConnectServer
      Set QfeSet = Service.ExecQuery("Select * From Win32_Process Where Caption='" & ProcessName & "'")
      For Each Qfe In QfeSet
      Qfe.Terminate
      Next
      End Sub


    コマンドプロンプトを利用すればもっとシンプルに実装できる。

    TerminateProcess関数のソース(コマンドプロンプト利用版)

      TerminateProcess("iexplore.exe")

      '-------------------------------------------------------------------------------
      ' 指定した名前のプロセスを強制終了する
      '-------------------------------------------------------------------------------
      Sub TerminateProcess(ProcessName)
      Dim objWS: Set objWS = CreateObject("WScript.Shell")

      ' 強制終了を実行(非表示のコマンドプロンプトで「TASKKILL」コマンドを実行させる)
      objWS.Run "cmd /c taskkill /f /im " & s & "*", 0, True
      End Sub


この記事での気付き

    VBScriptのみでの対応ではなく、コマンドプロンプトのハイブリット開発が効率的!
    • 文字列処理は、VBScript
    • プロセスの強制終了は、コマンドプロンプト
    といった具合に、得意な処理を分担させると無駄がなくスマート!!

    VBScriptに限らず、こういった処理系を使い分けるという考え方、超重要ですよ。
    親子の関係は「上司と部下」。「友達」には決してなるな!

2012/5/27掲載記事の更新。

今回開発したプログラムソース
# by yozda | 2021-01-01 11:26 | プログラミング | Comments(0)

[VBScript] 禁断の「Goto」ステートメントを実現する

どーもボキです。

初期化・終了処理をシンプルするためのGotoならば積極的に使うべき


サンプルソース

    Exit Do(≒GoTo)を活用した方が圧倒的に読みやすいことが分かると思う。

    Exit Do(≒GoTo)を活用したもの

      ' ------------------------------------------------------------------------------
      ' vbCommon.vbsデバッグ
      ' ------------------------------------------------------------------------------
      If objFS.GetFileName(WScript.ScriptFullName) = "vbCommon.vbs" Then
      ::::Do
      If InStr(LCase(WSCript.FullName), "wscript") = 0 Then Exit Do
      If Not Ping(サーバIP) Then Exit Do

      Dim fpth: fpth = "\" & サーバIP & "フォルダパスbCommon.vbs"
      If Not objFS.FileExists(fpth) Then Exit Do
      If objFS.GetFile(fpth).DateLastModified <= objFS.GetFile(WScript.ScriptFullName).DateLastModified Then Exit Do

      If objWS.Popup(WScript.ScriptFullName & "を更新します。",5, "プログラム更新", vbOkCancel + vbInformation) <> vbCancel Then
      objFS.CopyFile fpth, WScript.ScriptFullName, True
      End If
      ::::Loop Until 1
      SetScriptHost("cscript")

      dprintf "デバッグモード"
      End If


    Exit Do(≒GoTo)を活用せず、If文のみで表現したもの

      ' ------------------------------------------------------------------------------
      ' vbCommon.vbsデバッグ
      ' ------------------------------------------------------------------------------
      If objFS.GetFileName(WScript.ScriptFullName) = "vbCommon.vbs" Then
      If InStr(LCase(WSCript.FullName), "wscript") <> 0 Then
      ' WScriptホストでの実行
      If Ping(サーバIP) Then
      ' サーバにPingが通る
      Dim fpth: fpth = "\" & サーバIP & "フォルダパスbCommon.vbs"
      If objFS.FileExists(fpth) Then
      ' サーバにファイルが存在する
      If objFS.GetFile(fpth).DateLastModified > objFS.GetFile(WScript.ScriptFullName).DateLastModified Then
      ' サーバのファイルの方が新しい
      If objWS.Popup(WScript.ScriptFullName & "を更新します。",5, "プログラム更新", vbOkCancel + vbInformation) <> vbCancel Then
      ' キャンセルボタンが押されなかった(タイムアウトも含む)
      objFS.CopyFile fpth, WScript.ScriptFullName, True
      End If
      End If
      End If
      End If
      End If
      SetScriptHost("cscript")

      dprintf "デバッグモード"
      End If

2020/5/16 16:08掲載記事の更新
にほんブログ村 IT技術ブログへ
にほんブログ村
# by yozda | 2020-12-31 13:11 | プログラミング | Comments(0)

[VBScript] Windows APIなどのDLLを利用する

どーもボキです。

VBSでも(ひと手間かければ)Windows APIを呼べる。つまり、DLLを利用できる

    VBS単体では不可能なことも、事前にActiveXのDLLラッパーを仕込んでおけば、DLL利用が可能となる。
    DLLを呼べるようになれば、下図のようなメモ帳へのメッセージ出力も可能となる。
    [VBScript] Windows APIなどのDLLを利用する_a0021757_22050324.gif

サンプルのダウンロードと使い方

この記事での気付き

    VBSでのAPI利用は「不要」だろう。
    Notepadへのメッセージ出力も、cscriptを利用すれば解決できるし。

    うーん……、活用事例が思いつかない。

    ちなみに、サンプルはもともとExcelマクロ版WriteNoteをVBS用に修正したもの。
    Excelマクロの場合は、WriteNoteの利用がオススメ。Debug.Printの場合マクロ開発者以外は確認しづらいからね。

にほんブログ村 IT技術ブログへ
にほんブログ村

今回開発したプログラムソース
タグ:
# by yozda | 2020-12-30 22:34 | プログラミング | Comments(0)

[VBScript] ワイルドカードを指定したファイル名サーチ

どーもボキです。

ワイルドカードの指定が可能なファイル名サーチ関数「SearchFile」を用意した。

    FileExists関数(Scripting.FileSystemObjectのメソッド)は、ファイル存在判定が可能となる。
    ただし、ファイル名がわからない・固定できない場合、FileExists関数は適用できない。

    一方、CopyFile関数・MoveFile関数ならば、ワイルドカードでのファイル名指定が可能である。
    これを応用したものとなっている。

SearchFile関数の考え方

  1. 重複しない名前のフォルダを作成する。
  2. 1へ該当ファイル群を移動(MoveFile)する。
  3. 2からファイル名を取得する。
  4. 移動したファイル群を元のフォルダへ戻す(MoveFile)。
  5. 1で作成したフォルダを削除する。


SearchFile関数のソース

    ' 指定したファイル名が存在するか調べる(ワイルドカードOK)
    ' 戻り値:見つかったファイル名(最初に見つかったもの)
    Function SearchFile(DirectoryPath, FileName)
    Dim objFS,f,r,dpth

    r = ""
    On Error Resume Next

    Set objFS = CreateObject("Scripting.FileSystemObject")
    dpth = DirectoryPath & objFS.GetTempName
    objFS.CreateFolder(dpth) ' 重複しないフォルダを作成
    objFS.MoveFile DirectoryPath & FileName, dpth & "\"
    For Each f In objFS.GetFolder(dpth).Files
    r = f.Name
    Exit For
    Next
    objFS.MoveFile dpth & "\" & FileName, DirectoryPath
    objFS.DeleteFolder dpth

    On Error GoTo 0
    SearchFile = r
    End Function


この記事での気付き

    当初、重複しない名前のフォルダには、以下のように時間情報を利用していた。
    d = Now
    dname = Right(Year(d),2) & Right("0" & Month(d),2) & Right("0" & Day(d),2) & "_" & Right("0" & Hour(d),2) & Right("0" & Minute(d),2) & Right("0" & Second(d),2)

    SearchFileの適用する際、処理が1秒以内に終わることはなかったため、上記でも問題はなかったため、
    他のやり方を調べることすらしなかった。

    ある日、とある自作アプリが設定ファイルにランダム記名を採用していることに気付き、
    「これはどうやって命名しているのだろう?」
    と調べてみると、Scripting.FileSystemObject のGetTempNameに辿りつけた。

    Windows APIにもPath.GetTempFileName メソッドがあり、他の言語系でもランダム記名を取得するはできそう。

    こうやって、調べていく情報を辿っていくこと、頭の中で多くの情報が構造化され、
    新しい技術でもスッと理解できていくようになると思う。

    これまでの常識に疑問を持ち、より良い方法がないか考えてみること、
    より良い方法を見つけたら、今までの方法を変えていく。大事な考え方・行動ではないかと思っている。

にほんブログ村 IT技術ブログへ
にほんブログ村
2018/4/15 15:09掲載記事の更新

# by yozda | 2020-12-30 10:54 | プログラミング | Comments(0)

[VBScript] スクリプトをエンコードしてソースコードを読めなくする方法

どーもボキです。

VBScriptはメモ帳でもプログラム開発できる反面、見せたくないソースコードも配布しなければならない

    大半のプログラムは、実行プログラム形式で配布する。そのため、ソースコード自体は配布しなくてよい。
    しかしVBScriptは、実行プログラム=ソースコードとなる。そのため、ソースコード自体の配布は必須となる。

    それを避けたいならどうするか?

VBSファイルをエンコードすれば、配布したソースコードが読まれることはない

[VBScript] スクリプトをエンコードしてソースコードを読めなくする方法_a0021757_10173292.gif

サンプルのダウンロードと使い方

  • ダウンロード

  • 使い方
    エンコードは「encode.vbs」へVBSファイルをドロップ → VBEファイルが生成される。
    デコードは「decode.vbs」へVBEファイルをドロップ → VBSファイルが生成される。

    ※このエンコードは「Windows Script Encoder」(配布終了)と同じ技術が利用されている。
    ※VBEファイルをデコードすれば、もとのVBSファイルが編集可能となる。

参考サイト


エンコードしたVBEファイルはインクルード実行できない??

この記事での気付き

    配布終了となったWindows Script Encoder利用当時は、デコードできるなど思いもしなかった。
    とはいえ、会社でのVBScriptは、VBEでなく、VBSでの運用がほとんどだった。

    理由は、VBSソースを見る者などいなかったことと、PC情報に紐付くパスワード生成ルールにより、見られたとしても分からない仕組みだったこと、
    そして、そもそもボキ自体、VBEをインクルード実行できると思っていなかったからだ。

    外部ファイルをExecuteする方法を知って以来、ずっとこれが最適だと思っていた。

    wsfファイルならば、VBEファイルも取り込める、ファイルドロップ起動時もファイル名指定のみで外部ファイルを取り込める、
    今頃になって、すなおにwsfファイルを利用した方が賢かったことに気付けた。

    まずは標準の手順に打開策がないかを探すこと、それが大事。

にほんブログ村 IT技術ブログへ
にほんブログ村
# by yozda | 2020-12-28 22:58 | プログラミング | Comments(0)