VBAからPowershellを使ってExif撮影日付を取得(コンソール画面非表示） VBA Exif phototeken date

#新たな歴史を開く
##Windows 2000 Later Win以降か
これはwindows の clipという命令を使います
wscript execはコンソール画面が開いてしまうのが欠点でした。
なのでXpまではコンソール画面を回避することがむずかしい。
[WScript.ShellのExec()でコンソールアプリを非表示で実行する。](http://scripting.cocolog-nifty.com/blog/2007/05/wscriptshellexe_6e22.html)

しかし今回exifの撮影日付をpowershellで取得し、しかも、その時コンソール画面を表示させないということをします
まずこれはexcelのマクロです。
次に参照設定が必要です。Microsoft Forms 2.0 Object Library Refference Settings 見つからないときはsystem32\FM20.DLL
です。
 "E:\DSC0****.JPG" というJPGファイル（カメラで撮影したもの）の
撮影日付を取得します。

##EXCELのVBA

cmd = "Cmd /C PowerShell -nologo -command " & "Set-executionpolicy remotesigned -scope process -f;  " & """" & strps & "-sfilename" & " " & """'" & strFile & "'" & """ ***| clip***"
空白|空白clip
これがポイントで、撮影日付をクリップボードに渡すのです
oWSH.Run cmd, 0, True
そしてrunコマンドを使うことでウィンドが非表示です。
これだとパワーシェルに引数を渡しながらexec命令を使わなくても値を取得できるのです。
従来、execを使わなければ値は取得できず上記のような方法しかなかったのですが、Clipを使い　Runで非表示で値が取得できるのです。
そしてクリップボードを使うために参照設定をするのです。

[コマンドラインからクリップボードへコピーする](http://www.atmarkit.co.jp/fwin2k/win2ktips/609clipcmd/clipcmd.html)


```getphototekendate.vb
Sub phototeken()
'Microsoft Forms 2.0 Object Library Refference Settings
'QiiQ from Qiita
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = ActiveSheet
Dim strFile As String
strFile = "E:\DSC03286.JPG"
Dim oWSH: Set oWSH = CreateObject("WScript.SHell")
Dim FSO: Set FSO = CreateObject("Scripting.FIleSystemObject")
If FSO.fileexists(strFile) = False Then Exit Sub
Dim strps:
'in case of VBA, Choose one in two
strps = oWSH.ExpandEnvironmentStrings("%USERPROFILE%") & "\Documents\ ps_fnphototaken.ps1 "
'strps = Environ("USERPROFILE") & "\Documents\myscript\ps_fnphototaken.ps1 "
Dim cmd
Dim RET
Dim cb As DataObject
cmd = "Cmd /C PowerShell -nologo -command " & "Set-executionpolicy remotesigned -scope process -f;  " & """" & strps & "-sfilename" & " " & """'" & strFile & "'" & """ | clip"
oWSH.Run cmd, 0, True
On Error Resume Next
With New MSForms.DataObject
.GetFromClipboard
RET = CDate(.GetText)
Debug.Print RET
End With
On Error GoTo 0
If Err.Number <> 0 Then Debug.Print Err.Description: Err
Set FSO = Nothing: Set oWSH = Nothing
End Sub

```

##Powershell
"%USERPROFILE%"\Documents\ps_fnphototaken.ps1
というファイルをつくります

```ps_fnphototaken.ps1
#Set-ExecutionPolicy remotesigned -Scope process -f
Param([String[]]$sFileName)

# Functions from http://blog.cincura.net/233463-renaming-files-based-on-exif-data-in-powershell/

#PowerShell ISE Form is %USERPROFILE%"\Documents\> Set-ExecutionPolicy RemoteSigned -Scope Process -Force;.\Ps_FnPhototaken2.ps1 "E:\DSC03286.JPG";

#PowerShell ISE Form is %USERPROFILE%"\Documents\> Set-ExecutionPolicy RemoteSigned -Scope Process -Force;.\Ps_FnPhototaken2.ps1 ‘E:\DSC03286.JPG’;

 

function Get-ExifData([string]$file)
{
    #[Reflection.Assembly]::LoadFile('C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Drawing.dll') | Out-Null

    [Reflection.Assembly]::LoadFile('C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll') | Out-Null
    $image = New-Object System.Drawing.Bitmap -ArgumentList $file
    try {
        $takenData = GetTakenData($image)
        if ($takenData -eq $null) {
            return $null
        }
        $takenValue = [System.Text.Encoding]::Default.GetString($takenData, 0, $takenData.Length - 1)

        $taken = [DateTime]::ParseExact($takenValue, 'yyyy:MM:dd HH:mm:ss', $null).ToString("yyyy/MM/dd HH:mm:ss",[System.Globalization.CultureInfo]::InvariantCulture)
        return $taken
    }
    finally {
        $image.Dispose()
    }
}

function GetTakenData([object]$image) {
    try {
        return $image.GetPropertyItem(36867).Value
    }  
    catch {
        return $null
    }
}
return;