Nivazoo,关于Exe Export Function!

Kingron 2002-05-07 05:33:53
关于EXE Export 函数,请参考:
http://www.delphibbs.com/delphibbs/listQ?lid=096123
贴子ID 096123,
关键字:Exe文件输出函数,重新启动Windows,启动默认打

不过我也没有调试通过!!!!比以前好一些,可以Load到句柄,并且可以得到函数地址,但是不能正确调用,以调用就发生非法内存访问错误!

请大家讨论......
...全文
92 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
Kingron 2002-05-21
  • 打赏
  • 举报
回复
我猜想可能是ImageBase的问题?反正搞不清楚!
///**************下面是DFW的贴子***********************
问题:Exe文件输出函数,重新启动Windows,启动默认打印机管理程序 ( 积分:99, 回复:8, 阅读:67 )
分类:系统相关 ( 版主:luyear, zyy04 )
来自:qdyoung, 时间:1998-12-27 16:30:00, ID:96123 [显示:小字体 | 大字体]
1.在Delphi编写的Exe文件中输出函数,编译通过,但在另一个程序中无法
调用。如果把Exe改成DLL,则一切正常。Why? 像User.exe和Gdi.exe
(16位)就可以输出。

2. 在关闭系统对话框中选择重新启动计算机时按住Shift键可以只重新
启动Windows,如何程序实现。ExitWindows(EW_RESTARTWINDOWS,0)不行。

3. 为默认打印机创建一个快捷方式后,用ShellExecute运行可以启动默认
打印机管理程序。如果不创建快捷方式,如何直接启动。

提问题、看问题都艰难,所以都写在上面了。还好现在有EMail服务,要是能
通过EMail提问题就好了。



来自:O_O, 时间:1998-12-27 20:34:00, ID:96139
1.不知道你的编写exe文件是什么意思?象user.exe和gdi.exe 其实是dll文件,只
不过扩展名为exe罢了,你还是按dll的方式来编,至于生成的dll文件扩展名随你怎么
取,只要调用时用上全称(带扩展名)就可以了.


来自:O_O, 时间:1998-12-29 20:35:00, ID:96285
2.以下是来自inprise news group 对该问题的回答:
32-bit programs can't do that - they can only reboot the system.
Microsoft recommends writing a small 16-bit program that restarts
Windows and running that program from your 32-bit program.


来自:qdyoung, 时间:1998-12-30 18:32:00, ID:96357
1. 我有个大的可执行(Exe)文件,其中有一个对话框想在另一个程序(Exe)中
使用。使用DLL可以,当我的软件就得多出一个文件,我希望整个软件文件
少些(洁癖,:),这样容易维护。我现在想被调用Exe支持命令行,另一个程序
直接运行它就是。除此还有其它办法吗?使用OLE?就是开销(?)太大(?),
划不着。

2. 我写了个16位Exe确实可以。但Windows 95怎么实现呢,有没有现成的16位
Exe文件呢。我在32位程序中通过Thunk技术调用User.exe中的ExitWindows导致
关机,Why? Delphi的ExitWindows调用的是ExitWindowsEx.


来自:O_O, 时间:1998-12-30 19:58:00, ID:96359
1.我觉得你这样的思路不太好,如果你的二个程序共用一些资源如对话框,不如把它们
放到dll里,虽然多一些文件,但维护会更容易,程序也清晰许多,我不记得exe可以象
dll一样输出函数,感觉不可能.
2.为什么不在32位的程序里掉用那个16位的程序呢?既然M$都那样建议了.具体的原因
可能只有问m$去了.
3.据说有个TManager的控件可以将win95当一个DDE server来调用,不知到谁有,
因为不关心,我没下载用过,也忘了在那里了.


来自:qdyoung, 时间:1998-12-30 22:58:00, ID:96371
2. 我想知道Windows 95是怎么做的,有没有现成的16位Exe文件,或哪个文件
有这个功能,用什么命令行。在16位程序中调用ExitWindows,与在32位程序中
使用Thunk调用,同样的参数怎么结果不一样。而Windows98之类仍有大量的16
代码,大量地要使用Thunk。



来自:qdyoung, 时间:1999-1-12 12:42:00, ID:97717
斑竹应该把分数还给我:
1. Exe可以调用Exe的输出,不知道以前怎么一直试都不行, 现在一部到位:
program TestExe; //输出函数的Exe

uses
Windows;

procedure Test(p: PChar); export; stdcall;
begin
MessageBox(0, p, 'Test', MB_OK);
end;

exports
Test;

begin
end.

procedure TForm1.Button1Click(Sender: TObject); //另一APP中调用
var
lib: THandle;
Test: procedure(p: PChar); stdcall;
begin
lib := LoadLibrary('TestExe.exe');
if lib = 0 then
ShowError('Cannot load the module')
else
begin
@Test := GetProcAddress(lib, 'Test');
if @Test = nil then
ShowError('Cannot GetProcAddress')
else Test('This is a test');
FreeLibrary(lib);
end;
end;

2. 感谢http://www.experts-exchange.com/Q.10115419, 以下代码RestartWindows可以实现:
{$StackFrames On} //QT_Thunk needs a stack frame, Thunking call to 16-bit USER.EXE. The ThunkTrash argument allocates space on the stack for QT_Thunk
function LoadLibrary16(LibraryName: PChar): THandle; stdcall; external kernel32 index 35;
procedure FreeLibrary16(HInstance: THandle); stdcall; external kernel32 index 36;
function GetProcAddress16(Hinstance: THandle; ProcName: PChar): Pointer; stdcall; external kernel32 index 37;
procedure QT_Thunk; cdecl; external kernel32 name 'QT_Thunk';
var
hInst16: THandle;
GFSR: Pointer;
function RestartWindows: WordBool;
var
ThunkTrash: array[0..$20] of Word;
dw: DWord;
w: Word;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
Result := False;
Exit;
end;
ThunkTrash[0] := hInst16; //Prevent the optimizer from getting rid of ThunkTrash
hInst16 := LoadLibrary16('user.exe');
if hInst16 < 32 then
raise Exception.Create('Cannot load USER.EXE');
FreeLibrary16(hInst16); //Decrement the usage count. This doesn't really free the library, since USER.EXE is always loaded
GFSR := GetProcAddress16(hInst16, 'ExitWindows'); //Get the function pointer for the 16-bit function in USER.EXE
if GFSR = nil then
raise Exception.Create('Cannot get address of ExitWindows');
dw := EW_RestartWindows;
w := 0;
asm //Thunk down to USER.EXE
push dw { push arguments }
push w
mov edx, GFSR { load 16-bit procedure pointer }
call QT_Thunk { call thunk }
mov Result, ax { save the result }
end;
end;
{$StackFrames Off}

3. 感谢http://www.experts-exchange.com/Q.10115433, 以下代码ShowPrintSpool可以实现:
function ExecuteContextMenuCommand(hParent: THandle; sf: IShellFolder; childPidl: PItemIDList;
verb: string = ''; propPage: string = ''; pidlCount: UInt = 1): Boolean;
var
cm, cm2, cm3: IContextMenu;
ici: TCMInvokeCommandInfo;
pop : HMenu;
c: Cardinal;
begin
Result := False;
if sf.GetUIObjectOf(hParent, pidlCount, childPidl, IID_IContextMenu,nil, Pointer(cm)) <> NOERROR then Exit;
try
cm2 := cm as IContextMenu2;
cm := cm2;
try
cm3 := cm as IContextMenu3;
cm := cm3;
except
end;
except
end;
ZeroMemory(@ici, sizeOf(ici));
with ici do
begin
cbSize := sizeOf(TCMInvokeCommandInfo);
fMask := CMIC_MASK_FLAG_NO_UI;
hWnd := hParent;
lpVerb := PChar(verb);
lpParameters := PChar(propPage); //'Settings';
nShow := SW_SHOW;
end;
if verb <> '' then
Result := cm.InvokeCommand(ici) = NOERROR
else
begin
pop := CreatePopupMenu;
try
if Succeeded(cm.QueryContextMenu(pop, 0, 1, $7FFF, CMF_DEFAULTONLY)) then
begin
c := GetMenuDefaultItem(pop, 0, 0);
if c <> 0 then
begin
ici.lpVerb := MakeIntResource(c - 1);
Result := cm.InvokeCommand(ici) = NOERROR;
end;
end;
finally
DestroyMenu(pop)
end;
end
end;

function PidlToStr(sf: IShellFolder; childPidl: PItemIDList): string;
var
sr: _StrRet;
begin
Result := '';
if (sf = nil) or (childPidl = nil) then Exit;
sr.uType := STRRET_CSTR;
if sf.GetDisplayNameOf(childPidl,SHGDN_NORMAL,sr) = NOERROR then
case sr.uType of
STRRET_CSTR : Result := string(sr.cStr);
STRRET_OFFSET : Result := string(PChar(Cardinal(childPidl) + sr.uOffset));
STRRET_WSTR : Result := string(sr.pOleStr);
end;
end;

function DefaultPrinterDevice: string;
var
Device, Driver, Port: array [0..255] of Char;
Mode: THandle;
begin
Device := '';
with Printer do
if Printers.Count > 0 then
GetPrinter(Device, Driver, Port, Mode);
Result := Device;
end;

procedure ShowPrintSpool;
var
pidl1, pidl2: PItemIDList;
sf1, sf2: IShellFolder;
malloc: IMalloc;
el: IEnumIDList;
c: Cardinal;
sDefaultPrinter: string;
begin
if (SHGetSpecialFolderLocation(INVALID_HANDLE_VALUE, CSIDL_PRINTERS, pidl1) = NOERROR) and
(SHGetMalloc(malloc) = NOERROR) then
try
if (pidl1^.mkid.cb <> 0) and (SHGetDesktopFolder(sf1) = NOERROR) and
(sf1.BindToObject(pidl1, nil, IID_IShellFolder, Pointer(sf2)) = NOERROR) and
(sf2.EnumObjects(Application.Handle, High(Cardinal), el) = NOERROR) then
begin
sDefaultPrinter := DefaultPrinterDevice;
el.Reset;
while el.Next(1, pidl2, c) = NOERROR do
begin
if PidlToStr(sf2, pidl2) = s
墨梅无痕 2002-05-20
  • 打赏
  • 举报
回复
难!
是不是PE里面的Base Address有问题?
王集鹄 2002-05-20
  • 打赏
  • 举报
回复
Kingron 最好具体的代码贴出来。我到不了delphibbs
wylove 2002-05-12
  • 打赏
  • 举报
回复
gz老大的贴子!

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧