やること
VBA上でPowerShellを実行し、パスワードを生成することを考えます。
パスワードは最初が英字で、数字は最初に来てはいけない。
このとき、PowerShellを2回実行することとし、1回目は英字から1文字抽出するもので、2つめのスクリプトは英数字から抽出したランダムな文字列とします。(パスワード先頭を英字にしたいから)
そしてこれらの2つの結果をVBA上で連結し、パスワードとして使用します。
VBA上では、パスワードを生成するときはFunctionプロシージャを呼び出して生成することとし、呼び出すことでいつでもパスワードを生成することができるようにします。
環境
環境は以下となっています。
VBAバージョン | Microsoft Visual Basic for Applications 7.1 |
PowerShellバージョン | 5.1.18362.145 |
PowerShellスクリプト
使用するPowerShellスクリプトは下記で、「Get-Random」と「-join」になります。
Get-Random -input ([char[]](65..90 + 97..122))
このスクリプトを解説。
端的に言うと、このスクリプトは、ASCIIコードの65~90(英大文字)と97~122(英小文字)から一文字をランダムに抽出するものとなっています。
説明すると、Get-Random関数は、0 ~ 2,147,483,647の範囲から、ランダムにピックアップして返す関数です。「-input」パラメータを付けると、指定されたものからランダムにピックアップするようにすることができます。
([char[]](65..90 + 97..122))で、[char]65 ~ [char]90、[char]97 ~ [char]122 をくり返して実行します。[char]65はアスキーコード65番の文字を返すので、「A」が返ってくる。次は「B」「C」「D」というように英字のみを対象にして返し、その英字の中からランダムで一文字返すのが上記のスクリプトです。
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 7 | % {[char]$_})
このスクリプトは、数字(アスキーコード48~57)と英字をGet-Random関数に渡しています。英数字を渡されたGet-Random関数はその中から7個ピックアップし、% {[char]$_} に渡し文字列化します。そして最後に -join によって7つの英数字が連結されます。
ASCIIコードを下に記載しておきます。
補足:ASCIIコード表(10進数のみ)
Decimal | Symbol |
---|---|
0 | NUL |
1 | SOH |
2 | STX |
3 | ETX |
4 | EOT |
5 | ENQ |
6 | ACK |
7 | BEL |
8 | BS |
9 | HT |
10 | LF |
11 | VT |
12 | FF |
13 | CR |
14 | SO |
15 | SI |
16 | DLE |
17 | DC1 |
18 | DC2 |
19 | DC3 |
20 | DC4 |
21 | NAK |
22 | SYN |
23 | ETB |
24 | CAN |
25 | EM |
26 | SUB |
27 | ESC |
28 | FS |
29 | GS |
30 | RS |
31 | US |
32 | |
33 | ! |
34 | “ |
35 | # |
36 | $ |
37 | % |
38 | & |
39 | ‘ |
40 | ( |
41 | ) |
42 | * |
43 | + |
44 | , |
45 | – |
46 | . |
47 | / |
48 | 0 |
49 | 1 |
50 | 2 |
51 | 3 |
52 | 4 |
53 | 5 |
54 | 6 |
55 | 7 |
56 | 8 |
57 | 9 |
58 | : |
59 | ; |
60 | < |
61 | = |
62 | > |
63 | ? |
64 | @ |
65 | A |
66 | B |
67 | C |
68 | D |
69 | E |
70 | F |
71 | G |
72 | H |
73 | I |
74 | J |
75 | K |
76 | L |
77 | M |
78 | N |
79 | O |
80 | P |
81 | Q |
82 | R |
83 | S |
84 | T |
85 | U |
86 | V |
87 | W |
88 | X |
89 | Y |
90 | Z |
91 | [ |
92 | \ |
93 | ] |
94 | ^ |
95 | _ |
96 | ` |
97 | a |
98 | b |
99 | c |
100 | d |
101 | e |
102 | f |
103 | g |
104 | h |
105 | i |
106 | j |
107 | k |
108 | l |
109 | m |
110 | n |
111 | o |
112 | p |
113 | q |
114 | r |
115 | s |
116 | t |
117 | u |
118 | v |
119 | w |
120 | x |
121 | y |
122 | z |
123 | { |
124 | | |
125 | } |
126 | ~ |
127 |
プログラムコード
コードは以下のようになっています。
宣言
Sleep関数を使うので以下の宣言をします。
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
呼び出し元Subプロシージャ
String変数を宣言して、そこにパスワード生成プロシージャ(PasswdCreate)で生成したパスワードを格納し、イミディエイトウィンドウに表示するという、単純なものです。
'======================
'MainのSubプロシージャ
'======================
Sub Main()
Dim Password As String '生成したパスワードを受け取って格納する変数
Password = PasswdCreate 'パスワード生成プロシージャで作成したパスワードを変数に代入
Debug.Print Password 'イミディエイトウィンドウに表示
End Sub
呼び出し先Functionプロシージャ
これが主役のプロシージャです。
'====================================
'パスワード生成Functionプロシージャ
'====================================
Function PasswdCreate() As String
Dim RandomPW As String
Dim Cmd As String
Dim Wsh As Object
Cmd = "Get-Random -input ([char[]](65..90 + 97..122))"
Set Wsh = CreateObject("Wscript.shell").Exec("powershell -ExecutionPolicy RemoteSigned -Command " & Cmd)
Do While Wsh.Status = 0
Sleep 100
Loop
RandomPW = Wsh.StdOut.ReadAll
Cmd = "-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 7 | % {[char]$_})"
Set Wsh = CreateObject("Wscript.shell").Exec("powershell -NoLogo -ExecutionPolicy RemoteSigned -Command " & Cmd)
Do While Wsh.Status = 0
Sleep 100
Loop
RandomPW = RandomPW & Wsh.StdOut.ReadAll
RandomPW = Replace(RandomPW, vbCrLf, "")
Debug.Print RandomPW
PasswdCreate = RandomPW
End Function
パスワードを格納する変数が「RandomPW」です。
PowerShellのコマンドレットを格納する変数が「Cmd」です。
CreateObject関数でWscript.shellをインスタンス化してExecメソッドでCmd変数に格納したPowerShellコマンドレットを実行します。
1回目の実行では前述した「Get-Random -input ([char[]](65..90 + 97..122))」が実行され、RandomPW変数にランダムな英字1文字が格納されます。
2回目の実行では前述した「-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 7 | % {[char]$_})」が実行され、ランダムな英数字7文字がRandomPW変数の末尾につなげて格納されます。
最後に、「Replace(RandomPW, vbCrLf, “”)」で、RandomPW変数に入っている改行を空白に置き換えて一行のパスワードとします。
途中に入っているSleep関数で、100ミリ秒待機させているのは、PowerShellが起動して結果を返すまでに少し時間がかかるので、100ミリ秒待機させる処理をDo~Loopで実装し、結果が帰ってきたら処理を続行するようにしています。
実行結果
5回実行した結果をキャプチャで掲載いたします。

後書き
ランダムパスワードをVBAで生成する記事は散見されましたが、改行が含まれたString値を1行にすることに多少苦戦しました。
パスワードの最初が数字ではダメというようなときに使用できるTipsだったので、備忘録として記載しました。
最後前お読みいただき、ありがとうございました。
コメント