请看:
119、局域网中文件夹的共享 Windows NT/2000/XP
局域网中文件夹的共享 Windows NT/2000/XP
在局域网中通过程序实现文件夹的共享,就我知道的应该至少有两种实现方式。一是修改注册表,但是这种方法存在的问题也是很明显的,必须重起机器才能生效。二就是利用 Windows Api函数 NetShareAdd ,通过这个函数我们可以很容易的实现文件夹的共享,而且无需重起计算机。使用这个函数时我们必须注意的是在 Windows NT/2000/XP 和 Windows 95/98/Me 下用法是有很大差别的,这一点我相信大家都有体会,明明在 95 或 98 下实现好好的,可是一到 NT 下就出问题。
其实不光是各位仁兄,我早就提出过这个问题,怎奈一直都没有解决掉。现在好了,希望读完后能给大家一点点帮助。
Windows 95/98/Me 下 NetShareAdd 函数声明在 SVRAPI.DLL 动态连接库中,而在 2000/XP/NT 下声明在 NETAPI32.DLL 动态连接库中。所以我们在不同的操作系统下一定要注意调用不同的 DLL 库。这些函数详细的声明,在新版 MSDN 2002 中有介绍。由于在Delphi中没有声明这些函数和他们的参数所以我们要想实现这个函数还必须自己声明(可能delphi 有声明我不知道在那个单元中)。顺便说一句,我使用的是 delphi5.0 版,可惜他的帮助文件实在是太陈旧了,还是先看看 MSDN 2002 中关于 NetShareAdd 函数的声明巴!
Windows NT/2000/XP:
NET_API_STATUS NetShareAdd(
LPWSTR servername, //对应 Delphi 中 PWideChar
DWORD level, //对应 DELPHI 中 DWOED
LPBYTE buf, //对应 DELPHI 中 PBYTE
LPDWORD parm_err // 对应 DELPHI 中 PDWORD
);
Windows 95/98/Me: 下面的对应参数就不用说了吧!可以直接看看DELPHI帮助文件。
extern API_FUNCTION
NetShareAdd(
const char FAR * pszServer,
short sLevel,
const char FAR * pbBuffer,
unsigned short cbBuffer
);
特别强调:
我们在声明上面的函数时,函数参数一定要写对,也就是一定要正确对应到DELPHI 自己的类型上。不然函数功能无法实现,这一点我已经尝试了。之所以在NT 下实现不了主要还是,参数类型对应的不对。我们还需要声明一个记录类型,在98/95/me 和 nt/2000/xp下声明如下:
Windows NT/2000/XP: SHARE_INFO_2 和 SHARE_INFO_502 结构
Windows 95/98/Me: share_info_50 结构
对以上这个结构的声明更应该注意参数类型的正确对应。原始声明如下:
typedef struct _SHARE_INFO_502 {
LPWSTR shi502_netname; // PWideChar;
DWORD shi502_type; // DWORD;
LPWSTR shi502_remark; // PWideChar;
DWORD shi502_permissions; // DWORD;
DWORD shi502_max_uses; // DWORD;
DWORD shi502_current_uses; //DWORD;
LPWSTR shi502_path; //PWideChar;
LPWSTR shi502_passwd; // PWideChar;
DWORD shi502_reserved; // DWORD ;
// PSECURITY_DESCRIPTOR ;一般设为 Nil
PSECURITY_DESCRIPTOR shi502_security_descriptor;
} SHARE_INFO_502, *PSHARE_INFO_502, *LPSHARE_INFO_502;
对应 Delphi 纪录声明如下:一定要注意参数类型的正确对应,如果你把PWideChar 声明为 pchar 函数将无法实现此功能,我已经尝试了,你可以再试试,至于原因是什么,我也不太清楚。
type
TSHARE_INFO_502 = record
shi502_netname: PWideChar;
shi502_type: DWORD;
shi502_remark: PWideChar;
shi502_permissions: DWORD;
shi502_max_uses: DWORD;
shi502_current_uses: DWORD;
shi502_path: PWideChar;
shi502_passwd: PWideChar;
shi502_reserved: DWORD;
shi502_security_descriptor: PSECURITY_DESCRIPTOR;
end;
下面是完成的程序代码,其中有两部分,主程序和单元文件。运行环境 windows 2000 Ads 开发工具 Delphi5.0 。运行通过。
unit Share;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls,FileCtrl,My_Share;
type
TFormShare = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
BtSelect: TButton;
EditDir: TEdit;//文件共享目录
EditSharename: TEdit; //共享名称
EditInfo: TEdit;//备注
Button1: TButton;
Button2: TButton;
procedure BtSelectClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
FormShare: TFormShare;
implementation
{$R *.DFM}
procedure TFormShare.BtSelectClick(Sender: TObject);
var
directory: string;
begin
if SelectDirectory('选择一个目录','', directory) then
EditDir.Text := directory;
end;
procedure TFormShare.Button1Click(Sender: TObject);
begin
if EditDir.Text = '' then
begin
Application.MessageBox('请先选择一个目录!', '共享', MB_ICONINFORMATION + MB_OK);
BtSelect.Click;
Exit;
end;
if EditSharename.Text = '' then
begin
Application.MessageBox('请先输入共享名称!', '共享', MB_ICONINFORMATION + MB_OK);
EditSharename.SetFocus;
Exit;
end;
ShareResource('eengi',EditDir.Text,EditSharename.Text,EditInfo.Text);
{注意:如果在共享目录名称后面添加 $ 符号,共享后在网络邻居里看不到此文件夹但实际上已经共享了,你可以在本地看到}
end;
end.
以下是单元文件:
unit My_Share;
interface
uses
Windows,Sysutils ;
type
//纪录类型声明,注意参数类型的正确对应,最好别看 delphi 的帮助,引起误导
TSHARE_INFO_502 = record
shi502_netname: PWideChar;
shi502_type: DWORD;
shi502_remark: PWideChar;
shi502_permissions: DWORD;
shi502_max_uses: DWORD;
shi502_current_uses: DWORD;
shi502_path: PWideChar;
shi502_passwd: PWideChar;
shi502_reserved: DWORD;
shi502_security_descriptor: PSECURITY_DESCRIPTOR;
end;
//添加共享
function NetShareAdd(servername:Widestring; level: DWORD; Buf: PBYTE;
var parm_err: PDWORD ): DWORD; stdcall;
//删除共享
function NetShareDel(ServerName:Widestring; NetName: Widestring;
Reserved: DWord): Integer; StdCall;
const
{共享类型}
STYPE_DISKTREE = 0 ;
STYPE_PRINTQ = 1 ;
STYPE_DEVICE = 2 ;
STYPE_IPC = 3 ;
{访问权限}
ACCESS_READ = 0 ;
ACCESS_WRITE = 1 ;
ACCESS_CREATE = 2 ;
ACCESS_EXEC = 3 ;
ACCESS_DELETE = 4 ;
ACCESS_ALL = 7 ;
//自己声明的函数,为了调用方便,参数就不用说明了吧!
function ShareResource(ServerName,FilePath,NetName, Remark : string): Integer;
//function DeleteShare(ServerName: string; NetName: string): Integer;
implementation
//注意在 windows95/98/me 下面 dll 库是 SVRAPI.DLL ,而且参数类型也要随之改变的吆!
function NetShareAdd; external 'netapi32.DLL' name 'NetShareAdd';
function NetShareDel; external 'netapi32.DLL' name 'NetShareDel';
function ShareResource(ServerName,FilePath,NetName, Remark : string): Integer;
var
ShInfo: TSHARE_INFO_502;
parm_err
DWORD;
_FilePath,_NetName, _Remark : PWideChar ;
_ServerName : Pchar ;
begin
GetMem(_ServerName,255) ; //分配内存
GetMem(_FilePath,255);
GetMem(_NetName,255);
GetMem(_Remark,255);
StringToWideChar(FilePath,_FilePath,255); //字符串转换,一定要转换正确
StringToWideChar(NetName,_NetName,255);
StringToWideChar(Remark,_Remark,255);
strpcopy(_ServerName,ServerName);
//开始创建结构
with ShInfo do
begin
shi502_netname := _NetName;
shi502_type := STYPE_DISKTREE ;
shi502_remark := _Remark ;
shi502_max_uses := $FFFFFFFF;
shi502_current_uses := 10;
shi502_path := _FilePath;
shi502_passwd := nil;
shi502_reserved := 0;
shi502_security_descriptor := nil;
shi502_permissions := ACCESS_ALL;
end;
try
Result := NetShareAdd(_ServerName, 502, @ShInfo, parm_err);
Finally // 别忘了释放内存
FreeMem(_ServerName,255);
FreeMem(_FilePath,255);
FreeMem(_NetName,255);
FreeMem(_Remark,255);
end;
end;
end.
总结:
运行完程序后,相信大家和我有同样的感觉,其实成功就在眼前,就差一点,可是就这一点也很难跨越。程序之所以一直实现不了,恐怕我们都没有考虑参数类型声明是否正确。不过我应该非常感谢csdn 上“绝对菜鸟”的回复。要不是他的程序,恐怕我还在等待中探索