質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

1回答

2583閲覧

NetShareAddでAccessViolationException発生

yanna

総合スコア13

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

0クリップ

投稿2021/04/12 06:20

編集2021/04/12 13:38

内容

C#で共有フォルダを作成するプログラムを作成したいと思っています。
以下のネット情報を参考にそのまま実装したところAccessViolationExceptionが発生し、共有フォルダ作成に失敗してしまいます。
http://niyodiary.cocolog-nifty.com/blog/2009/08/c-3e14.html

例外が発生する原因や回避策について何かご存じの人いましたら、お手数ですが教えていただけないでしょうか?

環境

  • OS:Windows10
  • フレームワーク:.NET Framework 3.5

試したこと

fnShareAddメソッドには以下の引数を設定しているのですが、3つの環境で実行し、どの環境でも同様の例外が発生してしまいます。

  • サーバ名:null
  • 共有名:"share"

※共有名は重複していません

  • 最大接続数:10
  • コメント:""
  • パス:"C:"

※他のパスを設定しても例外は発生します

  • パスワード:""

NetShareAddメソッドの引数は上記URLと同様のものを設定しています。

調べたこと

以下のNetShareAddに関するMSDNは確認したのですが、例外についての記載はありませんでした。
https://docs.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netshareadd

また、AccessViolationExceptionについても調べたのですが、アンマネージコードで割り当てられていないメモリにアクセスしているから例外が発生していると解釈したのですが、対処としてどのようにすればよいかわかりませんでした。
https://docs.microsoft.com/ja-jp/dotnet/api/system.accessviolationexception?view=net-5.0

ソースコード(文字数オーバーのためコメントは一部消しています)

ShareFolderManager.cs

1 2using System; 3using System.Runtime.InteropServices; 4 5namespace ShareFolderSample 6{ 7 public static class ShareFolderManager 8 { 9 private const short STYPE_DISKETREE = 0; 10 private const int NERR_Success = 0; 11 /// <summary> 12 /// ユーザーには、要求した情報へのアクセス権がありません。 13 /// <summary> 14 private const int ERROR_ACCESS_DENIED = 5; 15 /// <summary> 16 /// level パラメータで指定した値が無効です。 17 /// <summary> 18 private const int ERROR_INVALID_LEVEL = 124; 19 /// <summary> 20 /// 文字またはファイルシステム名が無効です。 21 /// <summary> 22 private const int ERROR_INVALID_NAME = 123; 23 /// <summary> 24 /// 指定されたパラメータは無効です。 25 /// <summary> 26 private const int ERROR_INVALID_PARAMETER = 87; 27 /// <summary> 28 /// 指定した共有名は、既にこのサーバーで使われています。 29 /// <summary> 30 private const int NERR_DuplicateShare = 2118; 31 /// <summary> 32 /// リダイレクトされたリソースに対して、この操作は無効です。指定されたデバイス名は、 33 /// 共有リソースに割り当てられています。 34 /// <summary> 35 private const int NERR_RedirectedPath = 2117; 36 /// <summary> 37 /// デバイスまたはディレクトリが存在しません。 38 /// <summary> 39 private const int NERR_UnknownDevDir = 2116; 40 /// <summary> 41 /// 利用可能なメモリが不足しています。 42 /// <summary> 43 private const int ERROR_NOT_ENOUGH_MEMORY = 8; 44 /// <summary> 45 /// 指定された共有名が存在しません。 46 /// <summary> 47 private const int NERR_NetNameNotFound = 2310; 48 49 private struct SHARE_INFO_2 50 { 51 public int shi2_netname; 52 /// <summary> 53 /// 共有タイプ 54 /// </summary> 55 public int shi2_type; 56 /// <summary> 57 /// コメント 58 /// </summary> 59 public int shi2_remark; 60 /// <summary> 61 /// パーミッション 62 /// </summary> 63 public int shi2_permissions; 64 /// <summary> 65 /// 最大接続数 66 /// </summary> 67 public int shi2_max_uses; 68 /// <summary> 69 /// ? 70 /// </summary> 71 public int shi2_current_uses; 72 /// <summary> 73 /// 共有フォルダの絶対パス 74 /// </summary> 75 public int shi2_path; 76 /// <summary> 77 /// パスワード 78 /// </summary> 79 public int shi2_passwd; 80 81 private SHARE_INFO_2( 82 int shi2_netname, int shi2_type, int shi2_remark, int shi2_permissions, 83 int shi2_max_uses, int shi2_current_uses, int shi2_path, int shi2_passwd) 84 { 85 // VisualStudio2008でビルド警告を防ぐためだけに設定している 86 // この初期化処理は全く意味がない 87 this.shi2_netname = 0; // 文字列:null 88 this.shi2_type = 0; // 数値:0 89 this.shi2_remark = 0; // 文字列:null 90 this.shi2_permissions = 0; // 数値:0 91 this.shi2_max_uses = 0; // 数値:0 92 this.shi2_current_uses = 0; // 数値:0 93 this.shi2_path = 0; // 文字列:null 94 this.shi2_passwd = 0; // 文字列:null 95 } 96 } 97 [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] 98 private static extern int NetShareAdd( 99 string servername, int level, ref SHARE_INFO_2 buf, ref int parm_err); 100 101 [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] 102 private static extern int NetShareDel(string servername, string netname, int reserved); 103 104 public static void fnShareAdd( 105 string sServerName, string sShareName, int iMaxUses, string sComment, 106 string sPhysicsFolderPath, string sPassword) 107 { 108 SHARE_INFO_2 si2; 109 //------------------------------------------------------------------------------------- 110 // 共有フォルダの設定 111 //------------------------------------------------------------------------------------- 112 // 共有名 113 GCHandle gchNetName = GCHandle.Alloc(sShareName, GCHandleType.Pinned); 114 si2.shi2_netname = gchNetName.AddrOfPinnedObject().ToInt32(); 115 // 共有タイプ 116 si2.shi2_type = STYPE_DISKETREE; 117 // コメント 118 GCHandle gchNetRemark = GCHandle.Alloc(sComment, GCHandleType.Pinned); 119 si2.shi2_remark = gchNetRemark.AddrOfPinnedObject().ToInt32(); 120 // パーミッション 121 si2.shi2_permissions = 0; 122 // 最大接続数 123 si2.shi2_max_uses = iMaxUses; 124 // ? 125 si2.shi2_current_uses = 0; 126 // 共有フォルダパス 127 GCHandle gchPath = GCHandle.Alloc(sPhysicsFolderPath, GCHandleType.Pinned); 128 si2.shi2_path = gchPath.AddrOfPinnedObject().ToInt32(); 129 // パスワード 130 GCHandle gchPassword = GCHandle.Alloc(sPassword, GCHandleType.Pinned); 131 si2.shi2_passwd = gchPassword.AddrOfPinnedObject().ToInt32(); 132 //------------------------------------------------------------------------------------- 133 // 共有フォルダ作成 134 //------------------------------------------------------------------------------------- 135 int iParamErr = 0; 136 // 第二引数はSHARE_INFO_2構造体を使うことを示している(らしい) 137 int iResult = NetShareAdd(sServerName, 2, ref si2, ref iParamErr); 138 //------------------------------------------------------------------------------------- 139 // GCHandle解放 140 //------------------------------------------------------------------------------------- 141 gchNetName.Free(); 142 gchNetRemark.Free(); 143 gchPath.Free(); 144 gchPassword.Free(); 145 //------------------------------------------------------------------------------------- 146 // 戻り値判定 147 //------------------------------------------------------------------------------------- 148 switch (iResult) 149 { 150 case NERR_Success: 151 return; 152 case ERROR_ACCESS_DENIED: 153 throw new SystemException( 154 "ユーザーには、要求した情報へのアクセス権がありません。"); 155 case ERROR_INVALID_LEVEL: 156 throw new SystemException("level パラメータで指定した値が無効です。"); 157 case ERROR_INVALID_NAME: 158 throw new SystemException("文字またはファイルシステム名が無効です。"); 159 case ERROR_INVALID_PARAMETER: 160 throw new SystemException("指定されたパラメータは無効です。"); 161 case NERR_DuplicateShare: 162 throw new SystemException( 163 "指定した共有名は、既にこのサーバーで使われています。"); 164 case NERR_RedirectedPath: 165 throw new SystemException( 166 "リダイレクトされたリソースに対して、この操作は無効です。" + 167 "指定されたデバイス名は、共有リソースに割り当てられています。"); 168 case NERR_UnknownDevDir: 169 throw new SystemException("デバイスまたはディレクトリが存在しません。 "); 170 default: 171 string sMsg = string.Format( 172 "不明なエラー。NetShareAdd戻り値:{0}、iParamErr:{1}", 173 iResult, iParamErr); 174 throw new SystemException(sMsg); 175 } 176 } 177 public static void fnShareDel(string sServerName, string sShareName) 178 { 179 //------------------------------------------------------------------------------------- 180 // 共有フォルダ削除 181 //------------------------------------------------------------------------------------- 182 int iResult = NetShareDel(sServerName, sShareName, 0); 183 //------------------------------------------------------------------------------------- 184 // 戻り値判定 185 //------------------------------------------------------------------------------------- 186 switch (iResult) 187 { 188 case NERR_Success: 189 return; 190 case ERROR_ACCESS_DENIED: 191 throw new SystemException( 192 "ユーザーには、要求した情報へのアクセス権がありません。"); 193 case ERROR_INVALID_PARAMETER: 194 throw new SystemException("指定されたパラメータは無効です。"); 195 case ERROR_NOT_ENOUGH_MEMORY: 196 throw new SystemException("利用可能なメモリが不足しています。"); 197 case NERR_NetNameNotFound: 198 throw new SystemException("指定された共有名が存在しません。"); 199 default: 200 string sMsg = string.Format( 201 "不明なエラー。NetShareDel戻り値:{0}", iResult); 202 throw new SystemException(sMsg); 203 } 204 } 205 } 206} 207

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/04/12 13:01

参考にされたURLの記事は2009年8月と古く、.NET Coreは無い、.NET Frameworkのみであった頃のものです。また、Windows 10もまだリリースされていません。質問者さんが.NET Coreを使っているのであれば、.NET Frameworkを使うようにしてみればもしかしたら状況が変わるかもしれません。そういった、お使いの環境の詳細も質問文中に追記しましょう。
KOZ6.0

2021/04/12 13:04

コピペミスってこともあるので、ご自分の書いたコードを載せたほうがいいと思います。
yanna

2021/04/12 13:39

お二方、コメントありがとうございました。 追記しました。
KOZ6.0

2021/04/13 00:03

あーなるほど、32ビットなら動くっぽいコードですね。
yanna

2021/04/13 00:39

ありがとうございます。 プラットフォームターゲットをx86に設定するのを忘れていて、設定したところ例外が発生しなくなりました。
guest

回答1

0

ベストアンサー

API の宣言については、
http://pinvoke.net/
を参考にするといいと思います。

エラー値に関しては System.ComponentModel.Win32Exception を使用すると楽が出来ます。

あと、管理者モードで実行しないと ERROR_ACCESS_DENIED になります。

C#

1[StructLayout(LayoutKind.Sequential)] 2private struct SHARE_INFO_2 3{ 4 [MarshalAs(UnmanagedType.LPWStr)] 5 public string shi2_netname; 6 public int shi2_type; 7 [MarshalAs(UnmanagedType.LPWStr)] 8 public string shi2_remark; 9 public int shi2_permissions; 10 public int shi2_max_uses; 11 public int shi2_current_uses; 12 [MarshalAs(UnmanagedType.LPWStr)] 13 public string shi2_path; 14 [MarshalAs(UnmanagedType.LPWStr)] 15 public string shi2_passwd; 16} 17 18[DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] 19private static extern int NetShareAdd( 20 string servername, int level, ref SHARE_INFO_2 buf, ref int parm_err); 21 22public static void fnShareAdd( 23 string sServerName, string sShareName, int iMaxUses, string sComment, 24 string sPhysicsFolderPath, string sPassword) 25{ 26 SHARE_INFO_2 si2 = new SHARE_INFO_2(); 27 si2.shi2_netname = sShareName; 28 si2.shi2_type = STYPE_DISKETREE; 29 si2.shi2_remark = sComment; 30 si2.shi2_permissions = 0; 31 si2.shi2_max_uses = iMaxUses; 32 si2.shi2_current_uses = 0; 33 si2.shi2_path = sPhysicsFolderPath; 34 si2.shi2_passwd = sPassword; 35 int iParamErr = 0; 36 int iResult = NetShareAdd(sServerName, 2, ref si2, ref iParamErr); 37 if (iResult != NERR_Success) 38 { 39 throw new System.ComponentModel.Win32Exception(iResult); 40 } 41}

投稿2021/04/13 00:10

編集2021/04/13 00:13
KOZ6.0

総合スコア2644

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yanna

2021/04/13 13:48

確かにintではなくIntPtrが正しいことを確認しました。 IntPtrに変更すると、プラットフォームターゲットをx86に設定しなくても例外が発生しなくなりました。 教えていただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問