I am updating our "Printer Monitoring" application. Previously this application runs successfully on Windows 2000 server. Now we shifted to Windows 7 server. On windows 7 our "Print monitor" application crashes. When I debug it, I found that our SetJob function throws the following exception:
The parameter is incorrect.
Does anyone know anything about this?
Function call:
SetJob(
mhPrinter,
midJob,
0,
IntPtr.Zero,
PrintJobControlCommands.JOB_CONTROL_PAUSE) 'Here exception is thrown
Spooler API which we use :
<DllImport("winspool.drv", EntryPoint:="SetJob", _
SetLastError:=True, CharSet:=CharSet.Ansi, _
ExactSpelling:=False, _
CallingConvention:=CallingConvention.StdCall)> _
Public Function SetJob _
(<InAttribute()> ByVal hPrinter As IntPtr, _
<InAttribute()> ByVal dwJobId As Int32, _
<InAttribute()> ByVal Level As Int32, _
<InAttribute()> ByVal lpJob As IntPtr, _
<InAttribute(), MarshalAs(UnmanagedType.U4)> ByVal dwCommand As PrintJobControlCommands _
) As Boolean
Please have a loop here, how the function has to be build and how the parsmeters are called:
http://www.pinvoke.net/default.aspx/winspool.setjob
It is a bit different then you implemented it. Hope it will help.
Related
I wrote a small program in VB .Net to physically sort folder entries on FAT partitions (see http://www.public.bplaced.net). To do this, I use API calls to Kernel32.dll. I open the partition with CreateFileA, use the handle to lock the drive with DeviceIoControl FSCTL_LOCK_VOLUME and then read and write sectors directly with SetFilePointer / ReadFile / WriteFile (synchronous, with NO_BUFFERING).
All works PERFECTLY, except when I use my program with partitions larger than 2147483647 sectors (7FFF FFFF hex), WriteFile reports success but returns (and has) 0 byte written. This is the case no matter which sector I try to write. EVERYTHING else seems to still work as it should (including correct sector reading). When I use PartitionWizard to shrink the partition below the above limit, writing works again.
Question: does ANYBODY have a clue what could cause this strange behavior? My wild guess is that 'something' might interpret a value greater than 7FFF FFFF as 'signed'? Not within my code, the 'total sectors of partition' is not needed anywhere.
A friend also said that when he did something similar with 'streams', writing worked even with a 'large' partition...
I'm a total N00b, I can't even memorize all the terminology (but I still want to program so dearly...), so if you might have an explanation / hint / whatever, please describe it as simple-worded and detailled as possible.
Some code snippets (don't know where to start)... program is compiled for x86 systems. Problem occurs on both Win7 x86 and Win7 x64.
<DllImport("kernel32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function DeviceIoControl _
( _
ByVal hDevice As IntPtr, _
ByVal dwIoControlCode As UInteger, _
ByVal lpInBuffer As IntPtr, _
ByVal nInBufferSize As UInteger, _
ByVal lpOutBuffer As IntPtr, _
ByVal nOutBufferSize As UInteger, _
ByRef lpBytesReturned As UInteger, _
ByVal lpOverlapped As IntPtr _
) _
As Integer
End Function
Public Declare Function CreateFile Lib "kernel32" _
Alias "CreateFileA" ( _
ByVal lpFileName As String, _
ByVal dwDesiredAccess As Int32, _
ByVal dwShareMode As Int32, _
ByVal lpSecurityAttributes As IntPtr, _
ByVal dwCreationDistribution As Int32, _
ByVal dwFlagsAndAttributes As Int32, _
ByVal hTemplateFile As Int32 _
) _
As IntPtr
Public Declare Function SetFilePointer Lib "kernel32" _
( _
ByVal hFile As IntPtr, _
ByVal lpDistanceToMove As UInt32, _
ByRef lpDistanceToMoveHigh As Int32, _
ByVal dwMoveMethod As UInt32 _
) _
As UInt32
Public Declare Function WriteFile Lib "kernel32" _
( _
ByVal hFile As IntPtr, _
ByVal lpBuffer As Byte(), _
ByVal nNumberOfBytesToWrite As Int32, _
ByRef lpNumberOfBytesWritten As Int32, _
ByVal lpOverlapped As IntPtr _
) _
As Boolean
' **********************************************************
' open the partition by drive letter
devicehandle = CreateFile( _
"\\.\" & driveletter & ":", _
GENERIC_READ Or GENERIC_WRITE, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
IntPtr.Zero, _
OPEN_EXISTING, _
FILE_ATTRIBUTE_NORMAL Or FILE_FLAG_NO_BUFFERING, _
0 _
)
' **********************************************************
' lock the partition
Dim unused_lv As UInteger
Dim locked As Integer = DeviceIoControl( _
devicehandle, _
FSCTL_LOCK_VOLUME, _
IntPtr.Zero, _
0, _
IntPtr.Zero, _
0, _
unused_lv, _
IntPtr.Zero _
)
' **********************************************************
' set the file pointer, sector = sector to read, bytes_per_sector = 512. I use Bitconverter to get the hi and lo DWORDs
Dim s_bytes() As Byte = BitConverter.GetBytes(sector * bytes_per_sector)
' Hi-DWORD
Dim byte_dist_high As Int32 = BitConverter.ToInt32(s_bytes, 4) ' byte 4 - 7
' Lo-DWORD
Dim byte_dist_low As UInt32 = BitConverter.ToUInt32(s_bytes, 0) ' byte 0 - 3
' move file pointer
Dim move As UInt32 = SetFilePointer( _
devicehandle, _
byte_dist_low, _
byte_dist_high, _
FILE_BEGIN _
)
' **********************************************************
' write a sector
Dim write As Boolean = WriteFile( _
devicehandle, _
buffer, _
bytes_per_sector, _
bytes_written, _
IntPtr.Zero _
)
If write = False Then
Return False
Else
Return True
End If
While trying to create a handler using CreateFile(), even when executing the application as administrator, I get the following error message: ‘The system could not find the specified file. (Exception from HRESULT: 0x80070002)":Nothing.’
Here is a sample of the code being used for this task:
Private Enum EFileAccess As System.Int32
GENERIC_WRITE = &H40000000
End Enum
Friend Enum EFileShare
FILE_SHARE_READ = &H1
FILE_SHARE_WRITE = &H2
End Enum
Friend Enum ECreationDisposition
OPEN_EXISTING = 3
End Enum
Friend Enum EFileAttributes
FILE_FLAG_NO_BUFFERING = &H20000000
End Enum
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
Private Shared Function CreateFile(ByVal lpFileName As String, _
ByVal dwDesiredAccess As EFileAccess, _
ByVal dwShareMode As EFileShare, _
ByVal lpSecurityAttributes As IntPtr, _
ByVal dwCreationDisposition As ECreationDisposition, _
ByVal dwFlagsAndAttributes As EFileAttributes, _
ByVal hTemplateFile As IntPtr) As Microsoft.Win32.SafeHandles.SafeFileHandle
End Function
The path points to a matrix printer in a Windows Server 2003.
handle = CreateFile(\\brbhzpc001154\Epson_2180,
EFileAccess.GENERIC_WRITE,
EFileShare.FILE_SHARE_READ Or EFileShare.FILE_SHARE_WRITE,
IntPtr.Zero,
ECreationDisposition.OPEN_EXISTING,
EFileAttributes.FILE_FLAG_NO_BUFFERING,
IntPtr.Zero)
This application, when compiled works without any error in Windows XP, but when trying to execute in Windows 7, the error described above always happens.
There are solutions here suggesting that on Win7 changing OPEN_EXISTING to OPEN_ALWAYS will make it work on Win7, but with no explanation why.
I'm developing an application which needs to get the windows names that have been active while the application is running, currently i'm performing a Call to GetForegroundwindow() every half a second, but that's hardly accurate and i don't wanna put it to 100ms interval, i think it's just bad and not accurate, is there any system event that can done that for me?
Thanks.
-- UPDATE --
You could use SetWindowsHookEx to monitor the current Desktop, but this doesn't work in managed code. Instead, you must use SetWinEventHook.
You had asked how to use the SetWinEventHook p/Invoke method. Here is your answer:
First make sure this line is at the top of your code file:
Imports System.Runtime.InteropServices
Next, declare all that you need to invoke the call:
Public Const WINEVENT_OUTOFCONTEXT = &H0
'' Events are ASYNC
Public Const WINEVENT_SKIPOWNTHREAD = &H1
'' Don't call back for events on installer's thread
Public Const WINEVENT_SKIPOWNPROCESS = &H2
'' Don't call back for events on installer's process
Public Const WINEVENT_INCONTEXT = &H4
'' Events are SYNC, this causes your dll to be injected into every process
Public Declare Function SetWinEventHook Lib "user32.dll" _
(eventMin As UInteger, _
eventMax As UInteger, _
hmodWinEventProc As IntPtr, _
lpfnWinEventProc As IntPtr, _
idProcess As UInteger, _
idThread As UInteger, _
dwflags As UInteger) As IntPtr
Public Declare Function UnhookWinEvent Lib "user32.dll" _
(hWinEventHook As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
Public Delegate Sub WinEventProc( _
hWinEventHook As IntPtr, _
[event] As UInteger, _
hwnd As IntPtr, _
idObject As Integer, _
idChild As Integer, _
dwEventThread As UInteger, _
dwmsEventTime As UInteger)
Next, you declare a function and a new variable as a function with an address to that function:
Public Sub EventCallBack( _
hWinEventHook As IntPtr, _
[event] As UInteger, _
hwnd As IntPtr, _
idObject As Integer, _
idChild As Integer, _
dwEventThread As UInteger, _
dwmsEventTime As UInteger)
' Some code goes here
End Sub
Private eventProc As New WinEventProc(AddressOf EventCallBack)
Private hEventHook As IntPtr
Finally, you tie it all together, and you pass the following line of code to create your hook (0 and 255 are arbitrary numbers, replace them with the min and max message codes you want to watch):
hEventHook = SetWinEventHook(0, _
255, _
IntPtr.Zero, _
Marshal.GetFunctionPointerForDelegate(eventProc), _
0, _
0, _
WINEVENT_OUTOFCONTEXT)
And when your program has finished add the following line to an Application termination event, or the form's Dispose or Finalize methods:
UnhookWinEvent(hEventHook)
And this runs as expected on my test application.
Because I need to extract an icon from a file, but not the first icon, I cannot use the vb.net icon extraction function. The WIN32API function that should do this expects a pointer to an integer array.
How can I provide this type as a parameter?
Declare Function ExtractIconEx Lib "shell32.dll" Alias "ExtractIconExA" _
(ByVal lpszFile As String, _
ByVal nIconIndex As Integer, _
ByRef phiconLarge As Integer, _
ByRef phiconSmall As Integer, _
ByVal nIcons As Long) As Integer
Dim icons As integer()
ExtractIconEx("%systemroot%/shell32.dll", 15, icons, 0, 5)
I've taken a gander at the System.Reflection.Pointer class?/namespace?, but the documentation is sparse and less than sensible.
IntPtr doesn't provide support for arrays afaikt
Ok tx to Hans I've managed to correct the signature to:
<Runtime.InteropServices.DllImport("shell32.dll", _
CharSet:=Runtime.InteropServicesCharSet.Auto)> _
Shared Function ExtractIconEx(ByVal szFileName As String, _
ByVal nIconIndex As Integer, _
ByRef phiconLarge() As IntPtr, _
ByRef phiconSmall() As IntPtr, _
ByVal nIcons As UInteger) As UInteger
End Function
...
Dim icons(8) As IntPtr, smicons(8) As IntPtr
MsgBox(ExtractIconEx("%systemroot%/shell32.dll", 15, icons, smicons, 1))
Try
MsgBox(icons.Count)
Catch ex As Exception
MsgBox(ex.Message & " by " & ex.Source)
End Try
...
The subsequent calls always cause an exception (Value cannot be null). I get a return value of 4294967295, which is the maximum 32 bit integer value.
Any ideas how to tame this function and make it work?
ByRef phiconLarge() As IntPtr, _
ByRef phiconSmall() As IntPtr, _
The VB.NET declaration on that webpage has a bug, these arrays need to be passed ByVal, not ByRef. Note how they got it correct in the example code on the bottom of the page.
I edited the page to correct the bug.
I've purchased a license of BoxedAPP and when I wrote for help to the support mail I got any answer.
I've downloaded the SDK examples but all the important examples are in C# (and even if I use a translator I can't understand it), and the vb.net examples are for store files not executing they.
My question is simple, How I can use BoxedAPP to store a file in memory (Virtualize a file) and then execute it from memory?
For example I want to virtualize a Video file named "test.avi" as "my.resources.test" and then execute it with "process.start", this is what I've tryed to virtualize my recurse but don't run:
BoxedAppSDK.NativeMethods.BoxedAppSDK_CreateVirtualFile(My.Resources.test, _
BoxedAppSDK.NativeMethods.EFileAccess.GenericAll, _
BoxedAppSDK.NativeMethods.EFileShare.None, IntPtr.Zero, _
BoxedAppSDK.NativeMethods.ECreationDisposition.New, _
BoxedAppSDK.NativeMethods.EFileAttributes.Normal, _
IntPtr.Zero)
The first argument should be a string, check the function declaration:
<DllImport("bxsdk32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function BoxedAppSDK_CreateVirtualFile( _
ByVal lpFileName As String, _
ByVal dwDesiredAccess As EFileAccess, _
ByVal dwShareMode As EFileShare, _
ByVal lpSecurityAttributes As IntPtr, _
ByVal dwCreationDisposition As ECreationDisposition, _
ByVal dwFlagsAndAttributes As EFileAttributes, _
ByVal hTemplateFile As IntPtr) As IntPtr
End Function
Also what does BoxedAppSDK_CreateVirtualFile return?