Exe文件输出函数,重新启动Windows,启动默认打印机管理程序(99分)

  • 主题发起人 主题发起人 qdyoung
  • 开始时间 开始时间
Q

qdyoung

Unregistered / Unconfirmed
GUEST, unregistred user!
1.在Delphi编写的Exe文件中输出函数,编译通过,但在另一个程序中无法
调用。如果把Exe改成DLL,则一切正常。Why? 像User.exe和Gdi.exe
(16位)就可以输出。

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

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

提问题、看问题都艰难,所以都写在上面了。还好现在有EMail服务,要是能
通过EMail提问题就好了。
 
1.不知道你的编写exe文件是什么意思?象user.exe和gdi.exe 其实是dll文件,只
不过扩展名为exe罢了,你还是按dll的方式来编,至于生成的dll文件扩展名随你怎么
取,只要调用时用上全称(带扩展名)就可以了.
 
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.
 
1. 我有个大的可执行(Exe)文件,其中有一个对话框想在另一个程序(Exe)中
使用。使用DLL可以,当我的软件就得多出一个文件,我希望整个软件文件
少些(洁癖,:),这样容易维护。我现在想被调用Exe支持命令行,另一个程序
直接运行它就是。除此还有其它办法吗?使用OLE?就是开销(?)太大(?),
划不着。

2. 我写了个16位Exe确实可以。但Windows 95怎么实现呢,有没有现成的16位
Exe文件呢。我在32位程序中通过Thunk技术调用User.exe中的ExitWindows导致
关机,Why? Delphi的ExitWindows调用的是ExitWindowsEx.
 
1.我觉得你这样的思路不太好,如果你的二个程序共用一些资源如对话框,不如把它们
放到dll里,虽然多一些文件,但维护会更容易,程序也清晰许多,我不记得exe可以象
dll一样输出函数,感觉不可能.
2.为什么不在32位的程序里掉用那个16位的程序呢?既然M$都那样建议了.具体的原因
可能只有问m$去了.
3.据说有个TManager的控件可以将win95当一个DDE server来调用,不知到谁有,
因为不关心,我没下载用过,也忘了在那里了.
 
2. 我想知道Windows 95是怎么做的,有没有现成的16位Exe文件,或哪个文件
有这个功能,用什么命令行。在16位程序中调用ExitWindows,与在32位程序中
使用Thunk调用,同样的参数怎么结果不一样。而Windows98之类仍有大量的16
代码,大量地要使用Thunk。
 
斑竹应该把分数还给我:
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) = sDefaultPrinter then
ExecuteContextMenuCommand(Application.Handle, sf2, pidl2);
malloc.Free(pidl2);
end;
end;
finally
malloc.Free(pidl1);
end;
end;
 
不好意思,这几天感冒,没有过来。
我看O_O参与有功,酌情给分啦!
 
不好意思,这几天感冒,没有过来。
我看O_O参与有功,酌情给分啦!
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部