JobID, a pointer or just worthless?




I've got a fair amount of experience with 3rd party industrial fax
solutions, specifically GoldFax and loads of digi and BT boards on Nt4/2k
andf 2k3. In the end faxing is all pretty simple once you get the hardware
set up.

Over the weekend I started working the 2k/2k3/XP code and found it all very
simple too. For the most part it's identical to the older 3rd party

But one thing does strike me odd and I wonder if I'm just missing something.

(VB.Net code example)

dim oJobID as object
oJobID = oDoc.ConnectedSubmit(m_oSvr)

the value of oJobID is reported by Visual Studio as being an array of
Strings with a length of 1, so logic would be that using:

Debug.Writeline(Cstr( oJobId(0)) would tell you the actual and true JobID.
So that you could just take that ID and put it in a database and use it
directly later to get the status of the particular print/fax job.

At least, that's the way GoldFax and others work with their JobID returns of
their submission methods.

But instead to get the *actual JobID* with windows fax, you have to register
to receive the server event OnOutgoingJobAdded and in that event you get
the actual and true JobID.

This seems pretty silly to me. I mean, now you have to put your server
connection-closing code into the OnOutgoingJobAdded event stub rather then
just using a logical Send routine to get in, send the fax, get an ID and
get out clean.

Am I missing something here? The docs say that the C++ implementation of
ConnectedSubmit has a pointer to the address of the JobID array but that the
VB/Interop implementation instead returns an HRESULT.

Really I'm wondering what's the point of getting a value that MS calls a
"JobID" returned from ConnectedSubmit in the COM/Interop implementation? Is
that return a memory address that a VB/COM/Interop language has no use for
at all or can we use the return to get the real JobID using perhaps Unsafe
C# (not my forte, so I'd like to know if it's worth the effort before I try
to figure it out) ... or is the "JobID" just some unusable random non-zero
HRESULT value?

Kirkland, WA




Those returns just looked way too long to be addresses.

Oh, I get it.

JobID returns an array of strings (usually an array of a single element).
The element value is a string representation of an Int64. But a *Hex
string* of that value is used elsewhere else in MS Fax Services as the

Gee, that's soooo intuitive :)

So to get a JobID off of the ConnectedSubmit that you can save and use later
for polling the status of the Job you do this:

jID = fxdoc.ConnectedSubmit(m_objFax)
Dim str() As String = CType(jID, String())
Dim sJobRealID As String = str(0)
Dim lTmp As Int64 = CType(sJobRealID, Int64)
Debug.WriteLine(sJobRealID & vbTab & Hex(lTmp))

'puts in output window: 144613320835299231 201C50C922D779F

Put that second value in a db and use it last as in polling the outbound

Dim sLookForID as String = ("201C50C91B04E74").ToLower

objFaxOutgoingJob = objFaxOutgoingQueue.GetJob(sLookForID)
If Not objFaxOutgoingJob Is Nothing Then
MsgBox("Available operations: " & objFaxOutgoingJob.AvailableOperations &

Or, of course, you could save the original Int64 string to the db (or
convert it back to Int64 and save it to the DB that way) and do the Hex
string conversion later, whatever.

The question that probably will never be answered is: ""Why did MS think it
logical to have the JobID return value be a "String that is actually an
Int64 that is a Hex string everywhere else in the system"?


Robert Smith
Kirkland, WA

Raghavendra R [MSFT]

If you look at the documentation of ConnectedSubmit, it clearly mentions it
returns a Variant that specifies an array of outbound job ID strings, one
for each recipient of the fax. This is completely logical & intuitive. You
have a method that submits fax to multiple recipients & transmission to each
recipient is identified by a unique ID. Since that method has multiple
recipients it returns multiple IDs - array of IDs.

Unique ID in this context is a string. It's incorrect to interpret it as
anything else, because in future, the Unique ID can change to anything else
internally. Today it just happened to be a 64-bit variable in hex format.
The system (that is Fax Service Extended COM API) regards ID as string
everywhere - that's why you have FaxOutgoingQueue.GetJob having the first
parameter as string. So I didn't quite understand your last comment. As an
application developer the string ID is opaque to you. You should not try to
look inside it - this is where you add unnecessary assumptions in your code
that may break in future API releases.

Raghavendra R
Microsoft Printing, Imaging and Fax Team
This posting is provided "AS IS" with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.'

Bill Bartlett

Raghavendra, I think Robert's point is that the format of the job ID strings
is inconsistent between the value returned by the ConnectedSubmit call and
the jobId parameter passed back by all the event handlers. The underlying
_value_ returned is the same -- it is the unique ID of the fax job (a long
integer, it appears). However, ConnectedSubmit returns the job ID
(formatted as a character string) in decimal format (base 10), whereas the
event handlers pass back the job ID parameter (also formatted as a character
string) in hexadecimal format (base 16). Due to the differences in the
number format (decimal vs hexadecimal), it is impossible to match a job ID
from ConnectedSubmit with a job ID from the event handler without our
application interpreting and converting one value or the other.

For example, assume that your application submits a fax job and records the
job ID (as received from ConnectedSubmit) for that fax job into a database.
You later want to update the status of that fax job with the status as
received by the "outgoing queue" status events. In order to find the
correct row in the database for that fax job while processing the status
event, you must either convert the hexadecimal-format job ID received by the
status event from hex to decimal before looking for that job in your
database, or you must have previously converted the decimal-format job ID
value that was returned by ConnectedSubmit from decimal to hex before saving
it into the database. I do agree with you that we should not be trying to
interpret the job ID string value's contents, but it appears that we have no
choice but to do so.

(btw: Robert, thanks for confirming what I just discovered too, after
spending a chunk of time trying to determine why my database wasn't being
updated by my FaxQueueMonitor service...)

- Bill Bartlett


Thanks Bill, you hit the nail on the head.

If the ConnectedSubmit returned a bool result then of course the only way to
get the id for later queries of the queues would be to wait for the
OnOutgoingJobAdded event to fire and get it then. But the docs state that
the return is supposed to be the JobID(s) and also all of the docs
call/lable/name the return "JobID" (dim JobID as Variant) so by implication
that return should somehow relate to the value of the JobID. (and it does,
just that its base is funky).

I see Raghavendra's point in that we shouldn't compile that code and walk
away thinking it will work fine on Longhorn because by then they might go in
and fix the little issue, but I hope that most all code written for 2k3
Server will be fully tested before it's just tossed on a production Longhorn
box. Raghavendra, I will add a big note before that area of code and also
in the printed documentation that explains what is being done with the value
so that when/if the code is consdidered for a non-2k3 server install there
will be a point made to step through and verify that the return value
conversion does or doesn't need updating.

All the best, and my sincere thanks to both of you for your clarifications.

Robert Smith
Kirkland, WA

Raghavendra R [MSFT]

Yes, Bill what you said is correct. However on a Windows Server 2003,
ConnectedSubmit in fact returns the IDs in same format as the event handlers
(that is hex format).

Raghavendra R
Microsoft Printing, Imaging and Fax Team
This posting is provided "AS IS" with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.'



Bill Bartlett

Thanks for the heads-up on that -- since we're ultimately deploying to
Win2K3 servers, I would have hit this soon.

I noticed that you did increment the FaxServer.APIVersion value to reflect
the Win2K3 fax API as being different from the XP version (thanks!), so this
is easy to detect. For anyone else who's interested, here's my C# code to
check this:

private bool
CheckIfConnectedSubmitFaxJobIdFormatIsInHex(FAXCOMEXLib.FaxServer faxServer)
const long WIN2K3SVR_FAX_API_VERSION = 0x00020000; // this isn't
in the ENUM in the API we're developing with

if (faxServer.APIVersion ==

// Windows XP version -- job ID is returned in decimal format
return false;

} else if ( ( (long) faxServer.APIVersion ) ==

// Windows 2003 Server version -- job ID is returned in
hexadecimal format
return true;

} else {

// any other format -- we don't support you
throw new ApplicationException("Unsupported Fax API version: " +


- Bill Bartlett

Raghavendra R [MSFT]

Bill thanks for sharing the code. I have one suggestion. The logic can be
if (XP version) return FALSE
else return TRUE

So that you needn't change anything even when your program is deployed on a
new Operating System in future where API version will be different.

Raghavendra R
Microsoft Printing, Imaging and Fax Team
This posting is provided "AS IS" with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.'



Bill Bartlett

<grin> I thought about that, but my philosophy tends to be very conservative
when writing code that makes any assumptions on future platforms or API's.
I don't anticipate having to deal with a new platform for this code until
Longhorn, but rather than assume that the Longhorn version of the fax API
(or the fax API on a 64-bit version of Windows) will return this value the
same way that the Win2K3 version does, I'd rather explicitly test for that
when the time comes. (It's not that I don't trust anyone -- I just don't
trust anyone.)

However, we're also completely in control of on which platforms this code
will be run. If instead I were writing this for general distribution or for
a more open audience, I'd agree that it might make sense to assume that the
future versions will return the same value as the current, now-consistent
version does. That way you would only need to fix the code if that
assumption turns out to be wrong, versus having to fix the code no matter
what (to explicitly test for the additional future platforms).

- Bill Bartlett

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question