PowerShellã§ã¢ã³ãããŒãžãdllã䜿ãããšãããããã£ã話
ã¿ã€ãã«ã®ãšããã§ãããŸãããããªã«ããããšã¯æããŸããã§ããã
以åããExcelã§äœãããVBAãªãããPowerShellã§æžãçŽããŠããããšããããšããããã©ããªæãã«ãªãããªãŒãšæãããšããããŸããããããããšãã«ã¯å¿
ããšãã£ãŠããã»ã©VC++ãªã©ã§æžãããdllã䜿ã£ãŠiniãã¡ã€ã«ã®èªã¿èŸŒã¿ã ã£ãããã¡ã€ã«ã®å§çž®è§£åã ã£ãããããŠãããã®ã§ãããããããªããšãPowerShellãããåãããã«ãããã£ããã®ã䜿ãå¿
èŠãããã®ã§ã¯ãªãããšã
ããã§ããµãšæãç«ã£ãŠå§çž®ã§æåãªãUnlha32.dllããPowerShellã§äœ¿ã£ãŠã¿ãããšæããŸããããããããããŸã ã«ã»ãã¥ãªãã£ã«åé¡ããããšããŠã䜿ã£ãŠããäŒç€Ÿã¯å€ãã®ã§ã¯ãªãããšæããŸãããVBAããèªååããããã«ãã䜿çšãããŠããã®ã§ã¯ãªãããšæã£ãããã§ãã
ãªããUnlha32.dllã¯ãã§ã«éçºããŠããããæ¹ãã¢ããŠã³ã¹ãããŠãããšãããã»ãã¥ãªãã£ã§åé¡ãããã®ã§ãªã¹ã¹ã¡ã¯ããŸãããããã§ã¯åã«è©ŠããŠã¿ãã ããšããããšã§ãçè§£ãã ããã
äžå¿ãããã°æ¬æãšGistã®äž¡æ¹ã«ãµã³ãã«ã³ãŒããèšèŒããŠããŸãã
ã¢ã³ãããŒãžãdllãPowerShellã§äœ¿ãæ¹æ³
調ã¹ããšããããã£ããæžããŠãã£ãã®ã¯TechNetã®é£èŒèšäºã§ãããïŒæ¬ç«ãŠã«ãªã£ãŠãŸãã
Use PowerShell to Interact with the Windows API: Part 1 - Hey, Scripting Guy! Blog http://blogs.technet.com/b/heyscriptingguy/archive/2013/06/25/use-powershell-to-interact-with-the-windows-api-part-1.aspx
Use PowerShell to Interact with the Windows API: Part 2 - Hey, Scripting Guy! Blog http://blogs.technet.com/b/heyscriptingguy/archive/2013/06/26/use-powershell-to-interact-with-windows-apis-part-2.aspx
Use PowerShell to Interact with the Windows API: Part 3 http://blogs.technet.com/b/heyscriptingguy/archive/2013/06/27/use-powershell-to-interact-with-the-windows-api-part-3.aspx
èšäºãïŒæ¬ç«ãŠã«ãªã£ãŠããã®ã¯ãæ¹æ³ãïŒã€ããããã®ããã§ããä»åã¯Part1ã§ç޹ä»ãããŠããåçŽãããªæ¹æ³ãéžæããŸãããå¹çåããŠããããŒã«ãæžãæããã®ã«ãœãŒã¹ãé·ããªãã®ã¯ãããŠããããšããããšã§ãã
Part1ã§ç޹ä»ãããŠããæ¹æ³ã¯ãAdd-Typeãã䜿ããã®ã§ãããããäžçªãããããããã§ãããã€ãã«Part2ã§ã¯ã.Netã®ã¡ãœãããšããŠå®è¡ãããæ¹æ³ã§ããã¡ãã£ãšé·ããªã£ãŠããã®ã§ãããŸãããæåŸã«Part3ã§ã¯ãSystem.Reflectionãã䜿ã£ãæ¹æ³ã玹ä»ãããŠããŸãããããŸããããããšã«ãªã£ãŠããŸãã
ãšããããšã§ãä»åã¯Part1ã§æ¡çšãããŠããAdd-Typeã䜿ãããšã«ããŸããã
çµå±ã®ãšããããã®æ¹æ³ã§ã.Netã®ååãããã ããªããšã©ãã«ããªããŸãããå°ãã¿ããããããã§ãã
ãŸãã¯C#ãVB.netã§è¡ãããã«ãDllImportãã䜿ããŸãããããŠWin32APIã®é¢æ°ãå®çŸ©ããŸãã
$method = @' [DllImport("UNLHA32.DLL", CharSet = CharSet.Ansi)] public static extern int Unlha( IntPtr hwnd, // ãŠã£ã³ããŠãã³ãã« string szCmdLine, // ã³ãã³ãã©ã€ã³ System.Text.StringBuilder szOutput, // åŠççµææåå int dwSize); // åŒæ°szOutputã®æååãµã€ãº '@
ãããAdd-Typeã³ãã³ãã¬ããã§å®è¡ããŠãããšäœ¿ãããšãã§ããããã«ãªããŸãã Add-Typeã§ã¯ã-PassThruããã©ã¡ãŒã¿ãã€ããŠãåºåã§ã€ã³ã¹ã¿ã³ã¹ãååŸããŠããŸãããªããã-Languageããã©ã¡ãŒã¿ã§C#ãæå®ããŠããŸãããAdd-Typeã¯ããã©ã«ããC#ã«ãªã£ãŠããã®ã§å¥ã«æå®ããªããŠã倧äžå€«ã§ãã
æ£çŽãã¢ã³ãããŒãžãdllã䜿ãã ããªãããã§çµããã§ãã
ãŸãæåã«ã³ã³ãã€ã«ãšã©ãŒãåºãŸããã§å°ããŸãããäœãæªãã£ãããšãããšã颿°å®çŸ©ã®ãšããã§ãããStringBuilderãã¯ã©ã¹ã§DLLã®åºåãããã¡ãå®çŸ©ããŠããŸããããããèŠã€ãããªããåç
§ãäžè¶³ããŠãããšãããã®ã§ãããusingã远å ããããšæã£ãã®ã§ããããããããšããã«ãã¡ã§ãããããã¯èªæãšãããã€ãªã®ã§ãããããã§å®çŸ©ããããã®ã¯ã-NameSpaceããã©ã¡ãŒã¿ããã³ã-Nameãã§å®çŸ©ãããåå空éãã¯ã©ã¹ã®å
éšã«åã蟌ãŸããããã§ããã ããusingãªã©ã¯ããããªããšã«ãªããŸãã
ãšããããšã§ããã«ã§ãSystem.Text.StringBuilderããšããŠå®çŸ©ããŠããŸãã
ã€ãã«ããã£ãã®ã¯å®çŸ©ããUnlha颿°ã䜿ãããšãã§ããããã«ãªã£ãŠããªããšããå®è¡æãšã©ãŒã§ãããããã§ãããšãããexternãã远å ããŠããŸãããããŸãããããªããšããæãã§ãã
æåŸã«ãã£ããã ã£ãã®ããåäœç¢ºèªã«äœ¿ã£ãŠããWindowsã64bitãªã®ã«dllã¯32bitãšããããšã§ä»¥äžã®ãããªãšã©ãŒã«ãªããŸãããããã¯å®è¡æãšã©ãŒã§ãã
ééã£ããã©ãŒãããã®ããã°ã©ã ãèªã¿èŸŒãããšããŸããã (HRESULT ããã®äŸå€:0x8007000B)
æ®æ®µããŸãæèããªããªã£ãŠããŸããããUnlha32ã¯ååã®ãšãã32bitåãã«ã³ã³ãã€ã«ãããdllã§ãããã ãã64bitã§ã¯ãã®ãŸãŸã§ã¯äœ¿ãããšãã§ããŸãããããã§ãAdd-Typeã®ãã©ã¡ãŒã¿ã§ããã-CompilerParametersãã«ãã©ãããã©ãŒã æ
å ±ããªãã·ã§ã³ãšããŠæž¡ãããšãèããŸãããããããçµå±ãããåãçµæã«ãªããŸãããªããªãããããAdd-Typeããã³ãŒããx86åãã«ãªã£ããšããŠããPowerShellæ¬äœã64bitçã ããã§ãã
ããã§ã64bitçã®Windowsã«ã¯ã€ã³ã¹ããŒã«ãããŠãã32bitççšã®PowerShellã䜿ãããšã§ããŸããããŸããã
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell_ise.exe
ãããå°ããŸããã
ãšããããšã§ãå
šäœãæ²èŒããŠãããŸãã ã¡ãã£ãšèª¿ã¹ãè¶³ããªãã®ã§ããã32bitçã®PowerShell ISEã§åäœããããšçŸåšã®ãã©ã«ããšããŠã.ãã䜿ããš32bitçPowerShellã®å®è¡åœ¢åŒã眮ããŠãããã©ã«ãã«ãªããŸãããããã§æç€ºçã«ãããããšããŠãã¹ãæå®ããŠããŸãããŸãããã®ãµã³ãã«ã§ã¯æ¡åŒµåããps1ãã®ãã¡ã€ã«ã ããå§çž®ã®å¯Ÿè±¡ã«ããŠãããŸãã
$method = @' [DllImport("UNLHA32.DLL", CharSet = CharSet.Ansi)] public static extern int Unlha( IntPtr hwnd, // ãŠã£ã³ããŠãã³ãã« string szCmdLine, // ã³ãã³ãã©ã€ã³ System.Text.StringBuilder szOutput, // åŠççµææåå int dwSize); // åŒæ°szOutputã®æååãµã€ãº '@ $unlha = Add-Type -MemberDefinition $method -Name "Unlha32" -Namespace "Unlha" -PassThru -Language CSharp $dir = (pwd).Path $now = Get-Date -Format "yyyyMMddHHmmss" $archived = Join-Path $dir "archive-$now.lzh" $input = Join-Path $dir "*.ps1" $cmd = "a $archived $input" $output = [System.Text.StringBuilder](1024) $ret = 0 try{ $ret = $unlha::Unlha([System.IntPtr]0, $cmd, $output, $output.Capacity) if($ret -ne 0){ throw [System.ApplicationException]($output) } else { "Success ! $output" } } catch [Exception] { Write-Error ("ãšã©ãŒãçºç`n" + $Error.Item($Error.Count - 1)) throw [System.ApplicationException] }
Gistã¯ãã¡ãã§ãã
VBAã§32bitçWindowsã®ããã«äœã£ãŠããããŒã«è³ç£ã¯ãããããããšããªãã®è² åµã«ãªããããããŸããããããªãããããªãã¬ãã«ã®ãã®ã§ããããã©ãããå€ãããã§ãããããå¯èœãªãæ¥åããèŠçŽãã§ãããšè² åµãã©ãã«ãããªããŠããããªãã®ã¯ãããªã®ã§ããâŠé£ããã§ããã