Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
This section contains information about the CreatePrintAsyncNotifyChannel function and the IPrintAsyncNotifyChannel interface.
HRESULT
CreatePrintAsyncNotifyChannel(
IN LPCWSTR,
IN PrintAsyncNotificationType*,
IN PrintAsyncNotifyUserFilter,
IN PrintAsyncNotifyConversationStyle,
IN IPrintAsyncNotifyCallback*,
OUT IPrintAsyncNotifyChannel**
);
Printing components call the CreatePrintAsyncNotifyChannel function to create a notification channel. Der Kanal kann pro Drucker oder pro Server sein.
Die Druckkomponente kann einen Benachrichtigungskanal nur öffnen, wenn die Komponente vom Spooler geladen wird. Winspool.drv deaktiviert diese Funktion, wenn der Aufrufer innerhalb von Anwendungen ausgeführt wird - und nicht im Spoolerdienst. For example, when the application loads the driver to perform rendering, a call to CreatePrintAsyncNotifyChannel fails. Derselbe Aufruf ist jedoch erfolgreich, wenn der Treiber vom Spoolerdienst geladen wird.
Spoolss.lib bietet diese Funktionalität, sodass Portmonitore Kanäle öffnen können. Components that run inside the spooler and that are linked to Spoolss.lib can call the CreatePrintAsyncNotifyChannel function. Im folgenden Verfahren wird der Zweck der einzelnen Eingabeparameter in einem Aufruf dieser Funktion erläutert. Der erste Schritt in der Prozedur gilt für den ersten Parameter in dieser Funktion, der zweite Schritt gilt für den zweiten Parameter usw.
Geben Sie zum Erstellen eines Benachrichtigungskanals die folgenden Elemente an:
Der Name des Druckers oder Servers.
Der Benachrichtigungskanaltyp. Der Anrufer kann den Typ der Benachrichtigungen angeben, die über diesen Kanal gesendet werden sollen.
Der Benutzerfilter. Der Anrufer kann die Benutzer angeben, die Benachrichtigungen empfangen sollen, entweder denselben Benutzer wie der Benachrichtigungssender oder alle Benutzer.
Der Unterhaltungsfilter. Der Aufrufer muss angeben, ob es sich um einen unidirektionalen oder einen bidirektionalen Kanal handelt. To mark the channel as unidirectional, set the last parameter (of type IPrintAsyncNotifyChannel**) of CreatePrintAsyncNotifyChannel to NULL.
The IPrintAsyncNotifyCallback interface to be called when a notification comes back from the other end of the channel. This can be NULL, if the caller is not interested in receiving responses.
When CreatePrintAsyncNotifyChannel returns, the sixth parameter (of type IPrintAsyncNotifyChannel**) points to a memory location that contains the address of an IPrintAsyncNotifyChannel object. Dieses Objekt identifiziert den Kanal und wird verwendet, um Benachrichtigungen zu senden und den Kanal zu schließen.
IPrintAsyncNotifyChannel Interface
The IPrintAsyncNotifyChannel interface identifies a channel and is used to send notifications and to close the channel. When a printing component calls the CreatePrintAsyncNotifyChannel function to create a notification channel, the spooler service responds by providing an object that exposes the IPrintAsyncNotifyChannel interface.
This interface inherits from the IUnknown interface so that the clients of the spooler notification mechanism can implement either a COM or a C++ object. Die Schnittstellendeklaration im folgenden Codebeispiel zeigt diese Vererbung:
#define INTERFACE IPrintAsyncNotifyChannel
DECLARE_INTERFACE_(IPrintAsyncNotifyChannel, IUnknown)
{
STDMETHOD(QueryInterface)(
THIS_
REFIID riid,
void** ppvObj
) PURE;
STDMETHOD_(ULONG, AddRef)(
THIS
) PURE;
STDMETHOD_(ULONG, Release)(
THIS
) PURE;
STDMETHOD(SendNotification)(
THIS_
IN IPrintAsyncNotifyDataObject*
) PURE;
STDMETHOD(CloseChannel)(
THIS_
IN IPrintAsyncNotifyDataObject*
) PURE;
};
To send a notification, the sender calls the IPrintAsyncNotifyChannel::SendNotification method. Der Absender kann entweder die Druckkomponente sein, die den Kanal öffnet und Benachrichtigungen sendet, oder ein Überwachungsclient, wenn er auf eine Benachrichtigung reagieren muss. Diese Methode verhält sich asynchron. Wenn die Methode einen Erfolgscode zurückgibt, versucht der Spooler, die Benachrichtigung an Listener zu senden. Es gibt jedoch keine Garantie dafür, dass alle Listener die Benachrichtigung erhalten.
To close the channel, the sender or a listener can call the IPrintAsyncNotifyChannel::CloseChannel method. The caller can pass in a notification that gives the reason for closing the channel or can pass a NULL pointer. Wenn der Kanal geschlossen wird, werden alle Benachrichtigungen in der Warteschlange verworfen.
You must be careful in calling Release on a channel object, because it does not follow all the general COM programming invariants. You should call Release on IPrintAsyncNotifyChannel only if the following conditions occur:
If you called AddRef explicitly, and you must match it with a call to Release.
If you created the channel as unidirectional, and you must call Release one time on the pointer that you received as an output parameter. You should call Release after you have sent the desired notifications and closed the channel.
If you created the channel as bidirectional, you might have to call Release one time on the pointer that you received as an output parameter. You should call Release only if you do one or more of the following:
Before you call Release for a bidirectional channel, you must always call CloseChannel and receive a success result. You must not call Release if the call to CloseChannel fails, because the channel might have already been released on your behalf.
You must not call Release while entering the ChannelClosed event. To avoid this situation, check for a call to CloseChannel that has failed with the error CHANNEL_ALREADY_CLOSED. You do not have to call Release in this case, because the channel has already been released on your behalf.
You must not call CloseChannel, Release, or any other member function on the channel if your ChannelClosed callback function has finished running. In diesem Fall wurde der Kanal bereits freigegeben, sodass alle weiteren Aufrufe zu einem nicht definierten Verhalten führen können. Diese Einschränkung kann eine Koordination zwischen dem Vordergrundthread und dem Rückrufobjekt erfordern.
You must make sure that your foreground thread and callback object coordinate the call to CloseChannel and Release. Your foreground thread and your callback object cannot begin a call to CloseChannel if the other is about to call or has completed calling Release. You can implement this restriction by using the InterlockedCompareExchange routine. If you do not use InterlockedCompareExchange, you might cause undefined behavior.
If you registered as a listener on the channel, you can call CloseChannel and then call Release in your IPrintAsyncNotifyCallback::OnEventNotify callback function to end the bidirectional communication. However, you must not call CloseChannel or Release in your ChannelClosed callback.
If you meet one of these conditions, you must call Release. If you do not meet one of these conditions, you must not call Release.
Note
Calling Release under any of the preceding conditions but the first, in which you call AddRef explicitly, is an exception to general COM programming patterns. IPrintAsyncNotifyChannel differs from standard COM practice in this situation.