Windows系统共享文件夹或打印机等设备的dos脚本自动化

目录

目录

Windows系统共享文件夹或打印机等设备的dos脚本自动化

一、概述

        步骤:

        执行的结果:

二、脚本实作

        2.1、激活Windows的Administrator账户;

        2.2、设置Windows的Administrator账户的密码;

        2.3、重启Windows,并以Administrator账户登录(Logon);

        2.4、验证本机或远程计算机的管理组账号的Logon,登入该计算机

        2.5、共享对象的完整性访问控制列表ICACLS的“安全”授权

        2.6、共享对象的访问控制列表CACLS的“高级共享”授权

        2.7、需共享的文件夹或打印机等设备的“共享”授权

三、App中嵌入上述脚本运行(Delphi调用Windows Dos内部外部命令的脚本或PowerShell脚本的通行做法)

        3.1、将你的App进行UAC提权;

        3.2、调ShellExecute或ShellExecuteEx的Windows API函数执行上述脚本;

          3.2.1、例如:

          3.2.2、句法:

          3.2.3、Tray notification definitions托盘通知定义:


Windows系统共享文件夹或打印机等设备的dos脚本自动化

一、概述

        很多时候,我们需要通过App来共享本机或远程计算机的文件夹或打印机等设备。怎么做呢?

        步骤:

        1.1、激活Windows的Administrator账户;

        1.2、设置Windows的Administrator账户的密码;

        1.3、重启Windows,并以Administrator账户登录(Logon);

        1.4、验证本机或远程计算机的管理组账号的Logon,登入该计算机;

        1.5、共享对象的完整性访问控制列表的“安全”授权;

        1.6、共享对象的访问控制列表的“高级共享”授权;

        1.7、需共享的文件夹或打印机等设备的“共享”授权。

        执行的结果:

        就是替代了GUI的人机交互,用代码在App中自动化执行,比如就自动化实现了:

 网络文件夹(或打印机)共享的结果:

二、脚本实作

        步骤:(注意,首次配置,应当在本机执行,而不是在远程操作)

        2.1、激活Windows的Administrator账户;

        有些操作系统放入初始化安装,Administrator账户名被修改了,计算机账户的"凭据"就变了,所以需要:

        NET USER 将创建并修改计算机上的用户帐户。在不进行切换的情况下使用时,将列出
计算机的用户帐户。用户帐户信息存储在用户帐户数据库中。

net user administrator /active:yes

        2.2、设置Windows的Administrator账户的密码;

net user Administrator Adm****8

        2.1、和2.2、两步可以合二为一:

net user Administrator Adm****8 /active:yes

        2.3、重启Windows,并以Administrator账户登录(Logon);

shutdown -i -g -f

        2.4、验证本机或远程计算机的管理组账号的Logon,登入该计算机

以正确的密码验证本地或远程计算机的管理员账号,进行Logon登入:
netsh -r 192.168.3.242 -u Administrator -p Adm****8

        2.5、共享对象的完整性访问控制列表ICACLS的“安全”授权

icacls F:\我的开发测试文件夹 /grant Everyone:(D,WDAC)
rem 或具体某个登录账户的授权:
rem icacls F:\我的开发测试文件夹 /grant 计算机的某Logon账户:(D,WDAC)

        2.6、共享对象的访问控制列表CACLS的“高级共享”授权

cacls F:\我的开发测试文件夹 /T /G Everyone:F

        2.7、需共享的文件夹或打印机等设备的“共享”授权

net share MySharedFoderName=F:\我的开发测试文件夹 /GRANT:Everyone,FULL /UNLIMITED
rem MySharedFoderName为共享的友好名

这一步,会遇到与操作系统之间的交互式对话,可以用dos输入输出重定向:
echo off
echo Y | net share MySharedFoderName=F:\我的开发测试文件夹 /GRANT:Everyone,FULL /UNLIMITED

rem或将上述命令输出为批处理文件(MySharingFoder.bat)来执行.

三、App中嵌入上述脚本运行(Delphi调用Windows Dos内部外部命令的脚本或PowerShell脚本的通行做法)

        Delphi(或Lazarus类似稍改下即可)的话,步骤就是:

        3.1、将你的App进行UAC提权;

unit WinUtils;


{$WARN SYMBOL_PLATFORM OFF}
{$R+}

interface

uses
  Windows;

type
  TElevatedProc        = function(const AParameters: String): Cardinal;
  TProcessMessagesMeth = procedure of object;

var
//警告:此功能将在外部进程中执行。
//请勿在此例程中使用任何全局变量!
//仅使用提供的参数:
  OnElevateProc: TElevatedProc;

//分配完OnElevateProc后调用此例程:
procedure CheckForElevatedTask;

//以完全管理员权限运行OnElevateProc:
function RunElevated(const AParameters: String; const AWnd: HWND = 0; const AProcessMessages: TProcessMessagesMeth = nil): Cardinal; overload;

//以下4个函数判断并提权:
function  IsAdministrator: Boolean;//:当前Logon是管理员吗
function  IsAdministratorAccount: Boolean;//:当前Logon是管理员组吗
   //UAC(用户账户控制:User Account Control):
function  IsUACEnabled: Boolean;//:是否允许UAC的注册表检查
function  IsElevated: Boolean;//:提权

//比如,通过某个按钮的句柄来提权:
procedure SetButtonElevated(const AButtonHandle: THandle);


implementation

uses
  SysUtils, Registry, ShellAPI, ComObj;

const
  RunElevatedTaskSwitch = '0CC5C50CB7D643B68CB900BF000FFFD5'; // some unique value, just a GUID with removed '[', ']', and '-'

function CheckTokenMembership(TokenHandle: THANDLE; SidToCheck: Pointer; var IsMember: BOOL): BOOL; stdcall; external advapi32 name 'CheckTokenMembership';

function RunElevated(const AParameters: String; const AWnd: HWND = 0; const AProcessMessages: TProcessMessagesMeth = nil): Cardinal; overload;
var
  SEI: TShellExecuteInfo;
  Host: String;
  Args: String;
begin
  Assert(Assigned(OnElevateProc), 'OnElevateProc must be assigned before calling RunElevated');

  if IsElevated then
  begin
    if Assigned(OnElevateProc) then
      Result := OnElevateProc(AParameters)
    else
      Result := ERROR_PROC_NOT_FOUND;
    Exit;
  end;


  Host := ParamStr(0);
  Args := Format('/%s %s', [RunElevatedTaskSwitch, AParameters]);

  FillChar(SEI, SizeOf(SEI), 0);
  SEI.cbSize := SizeOf(SEI);
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  {$IFDEF UNICODE}
  SEI.fMask := SEI.fMask or SEE_MASK_UNICODE;
  {$ENDIF}
  SEI.Wnd := AWnd;
  SEI.lpVerb := 'runas';
  SEI.lpFile := PChar(Host);
  SEI.lpParameters := PChar(Args);
  SEI.nShow := SW_NORMAL;

  if not ShellExecuteEx(@SEI) then
   RaiseLastOSError;
  try

    Result := ERROR_GEN_FAILURE;
    if Assigned(AProcessMessages) then
    begin
      repeat
        if not GetExitCodeProcess(SEI.hProcess, Result) then
          Result := ERROR_GEN_FAILURE;
        AProcessMessages;
      until Result <> STILL_ACTIVE;
    end
    else
    begin
      if WaitForSingleObject(SEI.hProcess, INFINITE) <> WAIT_OBJECT_0 then
        if not GetExitCodeProcess(SEI.hProcess, Result) then
          Result := ERROR_GEN_FAILURE;
    end;

  finally
    CloseHandle(SEI.hProcess);
  end;
end;

function IsAdministrator: Boolean;
var
  psidAdmin: Pointer;
  B: BOOL;
const
  SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID  = $00000020;
  DOMAIN_ALIAS_RID_ADMINS      = $00000220;
  SE_GROUP_USE_FOR_DENY_ONLY  = $00000010;
begin
  psidAdmin := nil;
  try
    // Создаём SID группы админов для проверки
      //:创建一个SID管理组来检查psidAdmin:
    Win32Check(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
      SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
      psidAdmin));

    // Проверяем, входим ли мы в группу админов (с учётов всех проверок на disabled SID)
      //:检查psidAdmin是否属于管理组:
    if CheckTokenMembership(0, psidAdmin, B) then
      Result := B
    else
      Result := False;
  finally
    if psidAdmin <> nil then
      FreeSid(psidAdmin);
  end;
end;

{$R-}

function IsAdministratorAccount: Boolean;
var
  psidAdmin: Pointer;
  Token: THandle;
  Count: DWORD;
  TokenInfo: PTokenGroups;
  HaveToken: Boolean;
  I: Integer;
const
  SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID  = $00000020;
  DOMAIN_ALIAS_RID_ADMINS      = $00000220;
  SE_GROUP_USE_FOR_DENY_ONLY  = $00000010;
begin
  Result := Win32Platform <> VER_PLATFORM_WIN32_NT;
  if Result then
    Exit;

  psidAdmin := nil;
  TokenInfo := nil;
  HaveToken := False;
  try
    Token := 0;
    HaveToken := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, Token);
    if (not HaveToken) and (GetLastError = ERROR_NO_TOKEN) then
      HaveToken := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token);
    if HaveToken then
    begin
      Win32Check(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
        psidAdmin));
      if GetTokenInformation(Token, TokenGroups, nil, 0, Count) or
         (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then
        RaiseLastOSError;
      TokenInfo := PTokenGroups(AllocMem(Count));
      Win32Check(GetTokenInformation(Token, TokenGroups, TokenInfo, Count, Count));
      for I := 0 to TokenInfo^.GroupCount - 1 do
      begin
        Result := EqualSid(psidAdmin, TokenInfo^.Groups[I].Sid);
        if Result then
          Break;
      end;
    end;
  finally
    if TokenInfo <> nil then
      FreeMem(TokenInfo);
    if HaveToken then
      CloseHandle(Token);
    if psidAdmin <> nil then
      FreeSid(psidAdmin);
  end;
end;

{$R+}

function IsUACEnabled: Boolean;//UAC(用户账户控制,User Account Control)
var
  Reg: TRegistry;
begin
  Result := CheckWin32Version(6, 0);//:是Win7及其以后的版本?!
  if Result then//:如果是Win7及其以后的版本
  begin
    Reg := TRegistry.Create(KEY_READ);
    try
      Reg.RootKey := HKEY_LOCAL_MACHINE;//注册表的这个项:
      //HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
      if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\System', False)   
      then
        if Reg.ValueExists('EnableLUA') then
          Result := (Reg.ReadInteger('EnableLUA') <> 0)
        else
          Result := False
      else
        Result := False;
    finally
      FreeAndNil(Reg);
    end;
  end;
end;

function IsElevated: Boolean;
const
  TokenElevation = TTokenInformationClass(20);
type
  TOKEN_ELEVATION = record
    TokenIsElevated: DWORD;
  end;
var
  TokenHandle: THandle;
  ResultLength: Cardinal;
  ATokenElevation: TOKEN_ELEVATION;
  HaveToken: Boolean;
begin
  if CheckWin32Version(6, 0) then
  begin
    TokenHandle := 0;
    HaveToken := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, TokenHandle);
    if (not HaveToken) and (GetLastError = ERROR_NO_TOKEN) then
      HaveToken := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, TokenHandle);
    if HaveToken then
    begin
      try
        ResultLength := 0;
        if GetTokenInformation(TokenHandle, TokenElevation, @ATokenElevation, SizeOf(ATokenElevation), ResultLength) then
          Result := ATokenElevation.TokenIsElevated <> 0
        else
          Result := False;
      finally
        CloseHandle(TokenHandle);
      end;
    end
    else
      Result := False;
  end
  else
    Result := IsAdministrator;
end;

procedure SetButtonElevated(const AButtonHandle: THandle);
const
  BCM_SETSHIELD = $160C;
var
  Required: BOOL;
begin
  if not CheckWin32Version(6, 0) then
    Exit;
  if IsElevated then
    Exit;

  Required := True;
  SendMessage(AButtonHandle, BCM_SETSHIELD, 0, LPARAM(Required));
end;

procedure CheckForElevatedTask;

  function GetArgsForElevatedTask: String;

    function PrepareParam(const ParamNo: Integer): String;
    begin
      Result := ParamStr(ParamNo);
      if Pos(' ', Result) > 0 then
        Result := AnsiQuotedStr(Result, '"');
    end;

  var
    X: Integer;
  begin
    Result := '';
    for X := 1 to ParamCount do
    begin
      if (AnsiUpperCase(ParamStr(X)) = ('/' + RunElevatedTaskSwitch)) or
         (AnsiUpperCase(ParamStr(X)) = ('-' + RunElevatedTaskSwitch)) then
        Continue;

      Result := Result + PrepareParam(X) + ' ';
    end;

    Result := Trim(Result);
  end;

var
  ExitCode: Cardinal;
begin
  if not FindCmdLineSwitch(RunElevatedTaskSwitch) then
    Exit;

  ExitCode := ERROR_GEN_FAILURE;
  try
    if not IsElevated then
      ExitCode := ERROR_ACCESS_DENIED
    else
    if Assigned(OnElevateProc) then
      ExitCode := OnElevateProc(GetArgsForElevatedTask)
    else
      ExitCode := ERROR_PROC_NOT_FOUND;
  except
    on E: Exception do
    begin
      if E is EAbort then
        ExitCode := ERROR_CANCELLED
      else
      if E is EOleSysError then
        ExitCode := Cardinal(EOleSysError(E).ErrorCode)
      else
      if E is EOSError then
      else
        ExitCode := ERROR_GEN_FAILURE;
    end;
  end;

  if ExitCode = STILL_ACTIVE then
    ExitCode := ERROR_GEN_FAILURE;
  TerminateProcess(GetCurrentProcess, ExitCode);
end;
 { procedure KillProcess;
  var
    Msg: String;
  begin
    Msg :=
           'IsAdministrator: '        + BoolToStr(IsAdministrator, True) + sLineBreak +
           'IsAdministratorAccount: ' + BoolToStr(IsAdministratorAccount, True) + sLineBreak +
           'IsUACEnabled: '           + BoolToStr(IsUACEnabled, True) + sLineBreak +
           'IsElevated: '             + BoolToStr(IsElevated, True);
    MessageBox(0, PChar(Msg), 'Hello from RegisterExtension!', MB_OK or MB_ICONINFORMATION);
  KillTask(KillProcessName);
  showmessage(KillProcessName);
  end;  }

end.

        3.2、调ShellExecute或ShellExecuteEx的Windows API函数执行上述脚本;

          3.2.1、例如:

        Lcmd_Cacls_SharingDirName:='echo Y|cacls'+' '
          +trim(ADirectoryFullPath)
          +' '+'/C'+' '+'/G'+' ' + 'Everyone'+':F';

            LSharingCmd_bat:=GPath+'GYtemp' +PathDelim +'Ashare'+LDirName_NotWithDelimiAndPathPrefix +'.bat';
            LWinExecResult
              :=ShellExecute(
                Application.Handle,PChar('open'),
                PChar('"'+'c:\windows\system32\cmd.exe'+'"'), //:外部命令的可执行文件
                PChar(' /c '+'"'+LSharingCmd_bat+'"'),//:外部命令的参数
                nil,//:LPCTSTR lpDirectory运行的目录参数ShellAPI.pas
                SW_HIDE); //:外部命令的返回值无论成功与否------均42

          3.2.2、句法:

//ShellExecute组函数:
{$EXTERNALSYM ShellExecute}
function ShellExecute(hWnd: HWND; Operation, FileName, Parameters,
  Directory: PChar; ShowCmd: Integer): HINST; stdcall;
{$EXTERNALSYM ShellExecuteA}
function ShellExecuteA(hWnd: HWND; Operation, FileName, Parameters,
  Directory: PAnsiChar; ShowCmd: Integer): HINST; stdcall;
{$EXTERNALSYM ShellExecuteW}
function ShellExecuteW(hWnd: HWND; Operation, FileName, Parameters,
  Directory: PWideChar; ShowCmd: Integer): HINST; stdcall;


//ShellExecuteEx组函数:
{$EXTERNALSYM ShellExecuteEx}
function ShellExecuteEx(lpExecInfo: PShellExecuteInfo):BOOL; stdcall;
{$EXTERNALSYM ShellExecuteExA}
function ShellExecuteExA(lpExecInfo: PShellExecuteInfoA):BOOL; stdcall;
{$EXTERNALSYM ShellExecuteExW}
function ShellExecuteExW(lpExecInfo: PShellExecuteInfoW):BOOL; stdcall;



ShellExecuteEx组,其中PShellExecuteInfo:

type
  PShellExecuteInfoA = ^TShellExecuteInfoA;
  PShellExecuteInfoW = ^TShellExecuteInfoW;
  PShellExecuteInfo = PShellExecuteInfoA;
  {$EXTERNALSYM _SHELLEXECUTEINFOA}
  _SHELLEXECUTEINFOA = record
    cbSize: DWORD;
    fMask: ULONG;
    Wnd: HWND;
    lpVerb: PAnsiChar;
    lpFile: PAnsiChar;
    lpParameters: PAnsiChar;
    lpDirectory: PAnsiChar;
    nShow: Integer;
    hInstApp: HINST;
    { Optional fields }
    lpIDList: Pointer;
    lpClass: PAnsiChar;
    hkeyClass: HKEY;
    dwHotKey: DWORD;
    hIcon: THandle;
    hProcess: THandle;
  end;
  {$EXTERNALSYM _SHELLEXECUTEINFOW}
  _SHELLEXECUTEINFOW = record
    cbSize: DWORD;
    fMask: ULONG;
    Wnd: HWND;
    lpVerb: PWideChar;
    lpFile: PWideChar;
    lpParameters: PWideChar;
    lpDirectory: PWideChar;
    nShow: Integer;
    hInstApp: HINST;
    { Optional fields }
    lpIDList: Pointer;
    lpClass: PWideChar;
    hkeyClass: HKEY;
    dwHotKey: DWORD;
    hIcon: THandle;
    hProcess: THandle;
  end;
  {$EXTERNALSYM _SHELLEXECUTEINFO}
  _SHELLEXECUTEINFO = _SHELLEXECUTEINFOA;
  TShellExecuteInfoA = _SHELLEXECUTEINFOA;
  TShellExecuteInfoW = _SHELLEXECUTEINFOW;
  TShellExecuteInfo = TShellExecuteInfoA;
  {$EXTERNALSYM SHELLEXECUTEINFOA}
  SHELLEXECUTEINFOA = _SHELLEXECUTEINFOA;
  {$EXTERNALSYM SHELLEXECUTEINFOW}
  SHELLEXECUTEINFOW = _SHELLEXECUTEINFOW;
  {$EXTERNALSYM SHELLEXECUTEINFO}
  SHELLEXECUTEINFO = SHELLEXECUTEINFOA;

          3.2.3、Tray notification definitions托盘通知定义:

type
  PNotifyIconDataA = ^TNotifyIconDataA;
  PNotifyIconDataW = ^TNotifyIconDataW;
  PNotifyIconData = PNotifyIconDataA;
  {$EXTERNALSYM _NOTIFYICONDATAA}
  _NOTIFYICONDATAA = record
    cbSize: DWORD;
    Wnd: HWND;
    uID: UINT;
    uFlags: UINT;
    uCallbackMessage: UINT;
    hIcon: HICON;
    szTip: array [0..63] of AnsiChar;
  end;
  {$EXTERNALSYM _NOTIFYICONDATAW}
  _NOTIFYICONDATAW = record
    cbSize: DWORD;
    Wnd: HWND;
    uID: UINT;
    uFlags: UINT;
    uCallbackMessage: UINT;
    hIcon: HICON;
    szTip: array [0..63] of WideChar;
  end;
  {$EXTERNALSYM _NOTIFYICONDATA}
  _NOTIFYICONDATA = _NOTIFYICONDATAA;
  TNotifyIconDataA = _NOTIFYICONDATAA;
  TNotifyIconDataW = _NOTIFYICONDATAW;
  TNotifyIconData = TNotifyIconDataA;
  {$EXTERNALSYM NOTIFYICONDATAA}
  NOTIFYICONDATAA = _NOTIFYICONDATAA;
  {$EXTERNALSYM NOTIFYICONDATAW}
  NOTIFYICONDATAW = _NOTIFYICONDATAW;
  {$EXTERNALSYM NOTIFYICONDATA}
  NOTIFYICONDATA = NOTIFYICONDATAA;

const
  {$EXTERNALSYM NIM_ADD}
  NIM_ADD         = $00000000;
  {$EXTERNALSYM NIM_MODIFY}
  NIM_MODIFY      = $00000001;
  {$EXTERNALSYM NIM_DELETE}
  NIM_DELETE      = $00000002;

  {$EXTERNALSYM NIF_MESSAGE}
  NIF_MESSAGE     = $00000001;
  {$EXTERNALSYM NIF_ICON}
  NIF_ICON        = $00000002;
  {$EXTERNALSYM NIF_TIP}
  NIF_TIP         = $00000004;

{$EXTERNALSYM Shell_NotifyIcon}
function Shell_NotifyIcon(dwMessage: DWORD; lpData: PNotifyIconData): BOOL; stdcall;
{$EXTERNALSYM Shell_NotifyIconA}
function Shell_NotifyIconA(dwMessage: DWORD; lpData: PNotifyIconDataA): BOOL; stdcall;
{$EXTERNALSYM Shell_NotifyIconW}
function Shell_NotifyIconW(dwMessage: DWORD; lpData: PNotifyIconDataW): BOOL; stdcall;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专讲冷知识

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值