記事カテゴリ

ユーザー機能


 2024年4月24日(水) 06:13 JST

[Delphi] ネットワークドライブの割り当て/解除

  • 投稿者:
  • 表示回数
    13,445

ネットワークドライブを追加したいと思ったことはありませんか?通常企業などの場合、アプリケーションではなく起動時などにログオンスクリプトなどで割り当てすると思います。しかし、アプリケーションで割り当て、解除を行うことでアプリケーションを起動するまでのユーザーの操作にかかわらず安心して環境を構築できます。

ネットワークドライブを割り当てるには、WNetAddConnection2 APIを使用します。
また解除には、WNetCancelConnection2 APIを使用します。
さらにネットワークドライブの一覧の作成には、WNetOpenEnum と WNetEnumResource WNetCloseEnum の3つのAPIを使用します。
このAPIを3つの関数にしてみました。実際の使用方法はサンプルを見てください。

サンプルプログラムのダウンロードは→[Delphi FAQ用サンプル] ネットワークドライブの割り当て/解除

// WNet系APIエラー処理関数 
procedure NetErrorProc(err: DWORD); 
var
  s: string; 
begin
  case err of
    ERROR_ACCESS_DENIED:                s := ERR_ACCESS_DENIED; 
    ERROR_ALREADY_ASSIGNED:             s := ERR_ALREADY_ASSIGNED; 
    ERROR_BAD_DEV_TYPE:                 s := ERR_BAD_DEV_TYPE; 
    ERROR_BAD_NET_NAME:                 s := ERR_BAD_NET_NAME; 
    ERROR_BAD_PROFILE:                  s := ERR_BAD_PROFILE; 
    ERROR_BAD_PROVIDER:                 s := ERR_BAD_PROVIDER; 
    ERROR_BUSY:                         s := ERR_BUSY; 
    ERROR_CANCELLED:                    s := ERR_CANCELLED; 
    ERROR_CANNOT_OPEN_PROFILE:          s := ERR_CANNOT_OPEN_PROFILE; 
    ERROR_DEVICE_ALREADY_REMEMBERED:    s := ERR_DEVICE_ALREADY_REMEMBERED; 
    ERROR_EXTENDED_ERROR:               s := ERR_EXTENDED_ERROR; 
    ERROR_INVALID_PASSWORD:             s := ERR_INVALID_PASSWORD; 
    ERROR_NO_NET_OR_BAD_PATH:           s := ERR_NO_NET_OR_BAD_PATH; 
    ERROR_NO_NETWORK:                   s := ERR_NO_NETWORK; 
  else s := IntToStr(err); 
  end; 
  MessageDlg(s, mtError, [mbOk], 0); 
end; 
  
// ネットワークドライブの割り当て 
procedure AddNetworkDrive(Drive, UNC, Comment, Password, UserName: string); 
var
  NetResource: TNetResource; 
{$IFDEF UNICODE}
  user, pass: PWideChar; 
{$ELSE} 
  user, pass: PChar; 
{$ENDIF} 
begin
{$IFDEF UNICODE}
  with NetResource do
  begin
    dwType := RESOURCETYPE_DISK; 
    lpLocalName := PWideChar(Drive); 
    lpRemoteName := PWideChar(UNC); 
    lpComment := PWideChar(Comment); 
    lpProvider := nil; 
  end; 
  if (Password = '') then
    pass := nil
  else
    pass := PWideChar(password); 
  if (UserName = '') then
    user := nil
  else
    user := PWideChar(UserName); 
{$ELSE} 
  with NetResource do
  begin
    dwType := RESOURCETYPE_DISK; 
    lpLocalName := PChar(Drive); 
    lpRemoteName := PChar(UNC); 
    lpComment := PChar(Comment); 
    lpProvider := nil; 
  end; 
  if (Password = '') then
    pass := nil
  else
    pass := PChar(password); 
  if (UserName = '') then
    user := nil
  else
    user := PChar(UserName); 
{$ENDIF} 
  if (WNetAddConnection2(NetResource, pass, user, 0) <> NO_ERROR) then
  begin
    NetErrorProc(GetLastError); 
  end; 
end; 
  
// ネットワークドライブの接続解除 
procedure RemoveNetworkDrive(Drive: string); 
begin
  if (Drive = '') then exit; 
{$IFDEF UNICODE}
    WNetCancelConnection2(PWideChar(Drive), 0, true); 
//  WNetCancelConnection2(PWideChar(Drive[1]), 0, false); 
{$ELSE} 
    WNetCancelConnection2(PChar(Drive), 0, false); 
{$ENDIF} 
end; 
  
// ネットワークドライブの接続の列挙 
procedure EnumNetworkDrive(var sg: TStringGrid); 
type
  PNetResourceArray = ^TNetResourceArray; 
  TNetResourceArray = array[0..MaxInt div SizeOf(TNetResource) - 1] of TNetResource; 
const
  dwScope: DWORD = RESOURCE_CONNECTED; 
  dwType: DWORD = RESOURCETYPE_DISK; 
  dwUsage: DWORD = RESOURCEUSAGE_CONNECTABLE; 
var
  NetResource: TNetResource; 
  NetHandle: THandle; 
  i: integer; 
  NetResult: DWORD; 
  
  NetResources: PNetResourceArray; 
  BufSize: Integer; 
  Entries, Size: LongWord; 
  RowCnt: integer; 
begin
  with NetResource do
  begin
    dwType := RESOURCETYPE_DISK; 
    lpLocalName := nil; 
    lpRemoteName := nil; 
    lpComment := nil; 
    lpProvider := nil; 
  end; 
  if WNetOpenEnum(dwScope, dwType, dwUsage, @NetResource, NetHandle) <> NO_ERROR then
  begin
    NetErrorProc(GetLastError); 
    exit; 
  end; 
  RowCnt := 0; 
  try
    BufSize := 50 * SizeOf(TNetResource); 
    GetMem(NetResources, BufSize); 
    try
      while True do
      begin
        Entries := $FFFFFFFF; 
        Size := BufSize; 
  
        NetResult := WNetEnumResource(NetHandle, Entries, NetResources, Size); 
        if (NetResult = ERROR_MORE_DATA) then
        begin
          BufSize := Size; 
          ReallocMem(NetResources, BufSize); 
          continue; 
        end; 
        if (NetResult <> NO_ERROR) then
        begin
          if (NetResult <> ERROR_NO_MORE_ITEMS) then
            NetErrorProc(GetLastError); 
          exit; 
        end; 
  
        for i := 0 to Entries - 1 do
          with NetResources^[I] do
            if (lpLocalName <> nil) and (string(lpLocalName) <> '') then
            begin
              inc(RowCnt); 
              sg.Cells[C_DRIVE, RowCnt] := String(lpLocalName); 
              sg.Cells[C_PATH, RowCnt] := String(lpRemoteName); 
              sg.Cells[C_COMMENT, RowCnt] := String(lpComment); 
            end; 
      end; 
    finally
      FreeMem(NetResources, BufSize); 
    end; 
  finally
    WNetCloseEnum(NetHandle); 
    sg.RowCount := Max(RowCnt +1, 2); 
  end; 
end;

トラックバック

このエントリのトラックバックURL:
https://www.blackcat.xyz/trackback.php/ProgramingFAQ_del0027

以下のコメントは、その投稿者が所有するものでサイト管理者はコメントに関する責任を負いません。