トップ回答者
PowerShell上で常時Win32エラーコード203が発生している

質問
-
PowerShellコンソール上で
[System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
または
$cs=@' public class Test { public System.Int32 M() { return System.Runtime.InteropServices.Marshal.GetLastWin32Error(); } } '@ Add-Type -TypeDefinition $cs [Test]::new().M()
を実行すると、いつも203と表示されます。
Win32 APIをP/Invokeで使用するC#のコードをAdd-Typeで読み込んで使用したいのですが、最終エラーが常時発生している状態だとAPIのエラーに応じた処理に支障をきたすため非常に困っています。
一応、.NET Framework 4.7.2のコンパイラーのcsc.exeで
public class Test { public static void Main() { System.Console.WriteLine( System.Runtime.InteropServices.Marshal.GetLastWin32Error() ); } }
をコンパイルしてできたアプリを実行すると、ちゃんと0と表示されます。
環境はWindows 10 Pro 1809 (x64)、Windows PowerShell 5.1 (x64)です。
回答
-
この問題を解決する方法を見つけて自己解決しました。
それは、エラーの起こりそうな処理の前に予めWin32 APIのSetLastError()を呼び出して最終エラーをリセットしておくことでした。
C#のメソッドの中でSetLastError()で任意の最終エラーをセットすると、そのメソッドの中に限りMarshal.GetLastWin32Error()がセットした最終エラーの値を返してくれます。
検証コードは以下の通りです。
$cs = @' using System; using System.Runtime.InteropServices; public class Test { public readonly Int32 ErrorCode = 0; public readonly Int32 HResult = 0; public readonly Exception Error = null; [DllImport( @"kernel32.dll", EntryPoint = @"SetLastError", SetLastError = true )] private static extern void setLastError( UInt32 errorCode ); public Test( UInt32 errorCode ) { setLastError( errorCode ); this.ErrorCode = Marshal.GetLastWin32Error(); this.HResult = Marshal.GetHRForLastWin32Error(); this.Error = Marshal.GetExceptionForHR( this.HResult ); } } '@ Add-Type -TypeDefinition $cs $test = [Test]::new( [System.UInt32] 0 ) $test.ErrorCode $test.HResult $test.Error $test = [Test]::new( [System.UInt32] 5 ) $test.ErrorCode $test.HResult $test.Error
これを実行した結果は
0 -2147024896 この操作を正しく終了しました。 (HRESULT からの例外:0x80070000) 5 -2147024891 アクセスが拒否されました。 (HRESULT からの例外:0x80070005 (E_ACCESSDENIED))
と正しい値になっています。
また、正しい値を返すのはメソッドの中だけであり、メソッドが終了してから
[System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
とすると、相変わらず
203
と表示されます。
- 回答としてマーク fzok4234 2020年1月15日 4:19
すべての返信
-
こんにちは。フォーラムオペレーターのFanです。
フォーラムにご投稿くださいましてありがとうございます。
PowerShell上で常時Win32エラーコード203が発生していることについて
ご存知の方おりましたら、ご意見を共有頂ければ本当に幸いです.
どうぞよろしくお願いいたします。
Fan
Please remember to mark the replies as an answers if they help. If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com
-
この問題を解決する方法を見つけて自己解決しました。
それは、エラーの起こりそうな処理の前に予めWin32 APIのSetLastError()を呼び出して最終エラーをリセットしておくことでした。
C#のメソッドの中でSetLastError()で任意の最終エラーをセットすると、そのメソッドの中に限りMarshal.GetLastWin32Error()がセットした最終エラーの値を返してくれます。
検証コードは以下の通りです。
$cs = @' using System; using System.Runtime.InteropServices; public class Test { public readonly Int32 ErrorCode = 0; public readonly Int32 HResult = 0; public readonly Exception Error = null; [DllImport( @"kernel32.dll", EntryPoint = @"SetLastError", SetLastError = true )] private static extern void setLastError( UInt32 errorCode ); public Test( UInt32 errorCode ) { setLastError( errorCode ); this.ErrorCode = Marshal.GetLastWin32Error(); this.HResult = Marshal.GetHRForLastWin32Error(); this.Error = Marshal.GetExceptionForHR( this.HResult ); } } '@ Add-Type -TypeDefinition $cs $test = [Test]::new( [System.UInt32] 0 ) $test.ErrorCode $test.HResult $test.Error $test = [Test]::new( [System.UInt32] 5 ) $test.ErrorCode $test.HResult $test.Error
これを実行した結果は
0 -2147024896 この操作を正しく終了しました。 (HRESULT からの例外:0x80070000) 5 -2147024891 アクセスが拒否されました。 (HRESULT からの例外:0x80070005 (E_ACCESSDENIED))
と正しい値になっています。
また、正しい値を返すのはメソッドの中だけであり、メソッドが終了してから
[System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
とすると、相変わらず
203
と表示されます。
- 回答としてマーク fzok4234 2020年1月15日 4:19