I have a requirement, where I need to use IBM websphere message queue pub sub functionality.
Basically I have to write the subscriber part.
I need to know what all programming languages I can use to write the API other than java.
Can I write it using perl/shell/python?
There is PyMQI available for Python lovers. But note this offering is NOT from IBM.
Use MQ Client API. It does include samples for C++ like this one:
int main ( int argc, char * * argv ) {
ImqQueueManager mgr; // Queue manager
ImqQueue queue; // Queue
ImqMessage msg; // Data message
ImqGetMessageOptions gmo; // Get message options
char buffer[ 101 ]; // Message buffer
ImqChannel * pchannel = 0 ; // Channel definition
printf( "Sample IMQSGET start\n" );
if ( argc < 2 ) {
printf( "Required parameter missing - queue name\n" );
exit( 99 );
}
// Create object descriptor for subject queue
queue.setName( argv[ 1 ] );
if ( argc > 2 ) {
mgr.setName( argv[ 2 ] );
}
// Define a channel for client communication.
if ( argc > 3 ) {
ImqString strParse( argv[ 3 ] );
ImqString strToken ;
pchannel = new ImqChannel ;
pchannel -> setHeartBeatInterval( 1 );
// Break down the channel definition,
// which is of the form "channel-name/transport-type/connection-name".
if ( strParse.cutOut( strToken, '/' ) ) {
pchannel -> setChannelName( strToken );
if ( strParse.cutOut( strToken, '/' ) ) {
// Interpret the transport type.
if ( strToken.upperCase( ) == (ImqString)"LU62" ) {
pchannel -> setTransportType( MQXPT_LU62 );
}
if ( strToken.upperCase( ) == (ImqString)"NETBIOS" ) {
pchannel -> setTransportType( MQXPT_NETBIOS );
}
if ( strToken.upperCase( ) == (ImqString)"SPX" ) {
pchannel -> setTransportType( MQXPT_SPX );
}
if ( strToken.upperCase( ) == (ImqString)"TCP" ) {
pchannel -> setTransportType( MQXPT_TCP );
}
// Establish the connection name.
if ( strParse.cutOut( strToken ) ) {
pchannel -> setConnectionName( strToken );
}
}
}
mgr.setChannelReference( pchannel );
}
// Connect to queue manager
if ( ! mgr.connect( ) ) {
/* stop if it failed */
printf( "ImqQueueManager::connect failed with reason code %ld\n",
(long)mgr.reasonCode( ) );
exit( (int)mgr.reasonCode( ) );
}
// Associate queue with queue manager.
queue.setConnectionReference( mgr );
// Open the named message queue for input; exclusive or shared
// use of the queue is controlled by the queue definition here
queue.setOpenOptions(
MQOO_INPUT_AS_Q_DEF /* open queue for input */
+ MQOO_FAIL_IF_QUIESCING
); /* but not if MQM stopping */
queue.open( );
/* report reason, if any; stop if failed */
if ( queue.reasonCode( ) ) {
printf( "ImqQueue::open ended with reason code %ld\n",
(long)queue.reasonCode( ) );
}
if ( queue.completionCode( ) == MQCC_FAILED ) {
printf( "unable to open queue for input\n" );
}
// Get messages from the message queue
// Loop until there is a failure
msg.useEmptyBuffer( buffer, sizeof( buffer ) - 1 );
/* buffer size available for GET */
gmo.setOptions( MQGMO_WAIT | /* wait for new messages */
MQGMO_FAIL_IF_QUIESCING );
gmo.setWaitInterval( 15000 ); /* 15 second limit for waiting */
while ( queue.completionCode( ) != MQCC_FAILED ) {
// In order to read the messages in sequence, MsgId and
// CorrelID must have the default value. MQGET sets them
// to the values in for message it returns, so re-initialise
// them before every call
msg.setMessageId( );
msg.setCorrelationId( );
if ( queue.get( msg, gmo ) ) {
// Display each message received
if ( msg.formatIs( MQFMT_STRING ) ) {
buffer[ msg.dataLength( ) ] = 0 ; /* add terminator */
printf( "message <%s>\n", msg.bufferPointer( ) );
} else {
printf( "Non-text message\n" );
}
} else {
/* report reason, if any */
if ( queue.reasonCode( ) == MQRC_NO_MSG_AVAILABLE ) {
/* special report for normal end */
printf( "no more messages\n" );
} else {
/* general report for other reasons */
printf( "ImqQueue::get ended with reason code %ld\n",
(long)queue.reasonCode( ) );
/* treat truncated message as a failure for this sample */
if ( queue.reasonCode( ) == MQRC_TRUNCATED_MSG_FAILED ) {
break ;
}
}
}
}
// Close the source queue (if it was opened)
if ( ! queue.close( ) ) {
/* report reason, if any */
printf( "ImqQueue::close failed with reason code %ld\n",
(long)queue.reasonCode( ) );
}
// Disconnect from MQM if not already connected (the
// ImqQueueManager object handles this situation automatically)
if ( ! mgr.disconnect( ) ) {
/* report reason, if any */
printf( "ImqQueueManager::disconnect failed with reason code %ld\n",
(long)mgr.reasonCode( ) );
}
// Tidy up the channel object if allocated.
if ( pchannel ) {
mgr.setChannelReference( );
delete pchannel ;
}
printf( "Sample IMQSGET end\n" );
return( 0 );
}
IBM offers MQ clients for the following languages:
C, C++, .NET, Java
WebSphere MQ provides support for the following programming procedural languages:
C
Visual Basic (Windows systems only)
COBOL
Assembler language (WebSphere MQ for z/OS® only)
RPG (WebSphere MQ for IBM® i only)
PL/I (WebSphere MQ for z/OS only)
These languages use the message queue interface (MQI) to access message queueing services.
WebSphere MQ provides support for:
.NET
ActiveX
C++
Java
JMS
These languages use the WebSphere MQ Object Model, which provides classes that provide the same functionality as WebSphere MQ calls and structure.
Fuente
Related
I have a node.js server that takes data from a "sleepy" client over a websocket, then tries to push that data to the web client via its websocket. Sleepy means that it sleeps for a few minutes then wakes up to take a measurement and push the data, then back to sleep. See below:
sleepy client --> websocket--> node.js server --> websocket --> web clients
There is only one sleepy client but there can be multiple web clients. So when new data arrives, I need to push it to all web client web sockets. To keep track of this, I have an array that track web clients and stores their ctx info for later.
But, and this is the problem, when I try to push data to the web client websocket, I get a context error and node.js crashes.
Here is my code:
var globalCtx = [];
app.ws.use( function( ctx, next ) {
ctx.websocket.on('message', function ( message )
{
if( "telemetry" in jsonMsg )
{
console.log( "Got Telemetry: " );
console.log( message.toString() );
// we just got a telemetry message,
// so push it to the all the web client websockets
globalCtx.forEach( (myCtx, next) => {
console.log( "DEBUG: ", util.inspect(myCtx) ); <<<-----crashes here
myCtx.send( jsonMsg ); <<<----- or crashes here when not debugging
});
}
else
if( "webClient" in jsonMsg )
{
console.log( "Got WS Client: " );
console.log( message.toString() );
// we just got a web client connection message
// so store its context for pushing to later
if( Array.isArray( globalCtx ) && globalCtx.length )
{
// search for an existing entry
for( let idx = 0; idx < globalCtx.length; idx++ )
{
if( globalCtx[ idx ].ip == ctx.ip )
{
// we already have this IP stored, do nothing
console.log("IP already found: ", ctx.ip );
//return next( ctx );
return;
}
}
// we made it here, this means that the IP wasn't found
console.log("not found, adding IP: ", ctx.ip );
globalCtx.push( ctx );
}
else
{
// the array is empty, so just add it
console.log("empty array adding IP: ", ctx.ip );
globalCtx.push( ctx );
}
}
});
return next(ctx);
});
Here is the error:
/home/pi/node_modules/koa/lib/response.js:73
return this.res.statusCode;
^
TypeError: Cannot read property 'statusCode' of undefined
at Object.get status [as status] (/home/pi/node_modules/koa/lib/response.js:73:21)
at /home/pi/node_modules/only/index.js:6:20
at Array.reduce (<anonymous>)
at module.exports (/home/pi/node_modules/only/index.js:5:15)
at Object.toJSON (/home/pi/node_modules/koa/lib/response.js: 562:12)
at Object.toJSON (/home/pi/node_modules/koa/lib/context.js:5 1:31)
at Object.inspect (/home/pi/node_modules/koa/lib/context.js: 33:17)
at formatValue (internal/util/inspect.js:745:19)
at Object.inspect (internal/util/inspect.js:319:10)
at /home/pi/koaThermostat/index2.js:46:46
Here is the error from the myCtx.send( jsonMsg ); line
/home/pi/koaThermostat/index2.js:47
myCtx.send( jsonMsg );
^
TypeError: myCtx.send is not a function
at /home/pi/koaThermostat/index2.js:47:23
Well I feel silly! When using the Koa context with websockets, you have to use the websocket object. So in my case it should have been myCtx.websocket.send() not myCtx.send().
Now I'm on to my next bug....
I need to write code to download a file and the requirements are as follows. If the application is configured to use a proxy, attempt to download via the proxy. If that fails, attempt a direct connection. If no proxy is configured, attempt a direct connection. High-level pseudo-code:
if(ProxyEnabled)
if(!DownloadWithProxy())
DownloadWithoutProxy()
else
DownloadWithoutProxy()
I'm using WinHTTP since this code will be running in a service. The actual downloading is straightforward but I'm having issues with the proxy settings. My current pseudo-code is as follows:
hSession = WinHttpOpen(..., WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, ...)
hConnect = WinHttpConnect(hSession, ...)
hRequest = WinHttpOpenRequest(hConnect, ...)
if(Proxy.Enabled)
{
// set proxy server
WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, ServerName)
// set proxy credentials
WinHttpSetCredentials(hRequest, WINHTTP_AUTH_TARGET_PROXY, UserName, Password)
if(!DownloadFile(hRequest))
{
// reset proxy server
WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, NULL)
// reset proxy credentials
WinHttpSetCredentials(hRequest, WINHTTP_AUTH_TARGET_PROXY, NULL, NULL)
DownloadFile(hRequest)
}
}
else
{
DownloadFile(hRequest)
}
Where DownloadFile() does the standard WinHttpSendRequest() and WinHttpReceiveResponse() sequence. Everything works fine except in the case where the download via the proxy fails. When that happens the call to WinHttpSetCredentials() to reset the credentials fails (with ERROR_INVALID_PARAMETER), and as a result the second call to DownloadFile() still tries to use the proxy (even though I reset it) and the credentials. NOTE: In this specific scenario I am using a valid proxy server but invalid proxy credentials to trigger the failure.
So I guess my question is what is the best approach? As far as I can tell it is not possible to reset the credentials set via WinHttpSetCredentials(), so I guess I should just recreate the request for each call to DownloadFile() rather than trying to be "clever" by reusing a single request object.
WinHttpSetCredentials() takes 6 parameters, one of which is the auth scheme. You have only shown 4 parameters, and do not say which auth scheme you are using. Overall, your sequence for authenticating is different than what MSDN suggests:
Authentication in WinHTTP
A typical WinHTTP application completes the following steps in order to handle authentication.
•Request a resource with WinHttpOpenRequest and WinHttpSendRequest.
•Check the response headers with WinHttpQueryHeaders.
•If a 401 or 407 status code is returned indicating that authentication is required, call WinHttpQueryAuthSchemes to find an acceptable scheme.
•Set the authentication scheme, username, and password with WinHttpSetCredentials.
•Resend the request with the same request handle by calling WinHttpSendRequest.
Also take note of this condition:
The credentials set by WinHttpSetCredentials are only used for one request. WinHTTP does not cache the credentials to use in other requests, which means that applications must be written that can respond to multiple requests. If an authenticated connection is re-used, other requests may not be challenged, but your code should be able to respond to a request at any time.
The documentation linked above includes the following code example for how to use WinHTTPSetCredentials() correctly:
#include <windows.h>
#include <winhttp.h>
#include <stdio.h>
#pragma comment(lib, "winhttp.lib")
DWORD ChooseAuthScheme( DWORD dwSupportedSchemes )
{
// It is the server's responsibility only to accept
// authentication schemes that provide a sufficient
// level of security to protect the servers resources.
//
// The client is also obligated only to use an authentication
// scheme that adequately protects its username and password.
//
// Thus, this sample code does not use Basic authentication
// becaus Basic authentication exposes the client's username
// and password to anyone monitoring the connection.
if( dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NEGOTIATE )
return WINHTTP_AUTH_SCHEME_NEGOTIATE;
else if( dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NTLM )
return WINHTTP_AUTH_SCHEME_NTLM;
else if( dwSupportedSchemes & WINHTTP_AUTH_SCHEME_PASSPORT )
return WINHTTP_AUTH_SCHEME_PASSPORT;
else if( dwSupportedSchemes & WINHTTP_AUTH_SCHEME_DIGEST )
return WINHTTP_AUTH_SCHEME_DIGEST;
else
return 0;
}
struct SWinHttpSampleGet
{
LPCWSTR szServer;
LPCWSTR szPath;
BOOL fUseSSL;
LPCWSTR szServerUsername;
LPCWSTR szServerPassword;
LPCWSTR szProxyUsername;
LPCWSTR szProxyPassword;
};
void WinHttpAuthSample( IN SWinHttpSampleGet *pGetRequest )
{
DWORD dwStatusCode = 0;
DWORD dwSupportedSchemes;
DWORD dwFirstScheme;
DWORD dwSelectedScheme;
DWORD dwTarget;
DWORD dwLastStatus = 0;
DWORD dwSize = sizeof(DWORD);
BOOL bResults = FALSE;
BOOL bDone = FALSE;
DWORD dwProxyAuthScheme = 0;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen( L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0 );
INTERNET_PORT nPort = ( pGetRequest->fUseSSL ) ?
INTERNET_DEFAULT_HTTPS_PORT :
INTERNET_DEFAULT_HTTP_PORT;
// Specify an HTTP server.
if( hSession )
hConnect = WinHttpConnect( hSession,
pGetRequest->szServer,
nPort, 0 );
// Create an HTTP request handle.
if( hConnect )
hRequest = WinHttpOpenRequest( hConnect,
L"GET",
pGetRequest->szPath,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
( pGetRequest->fUseSSL ) ?
WINHTTP_FLAG_SECURE : 0 );
// Continue to send a request until status code
// is not 401 or 407.
if( hRequest == NULL )
bDone = TRUE;
while( !bDone )
{
// If a proxy authentication challenge was responded to, reset
// those credentials before each SendRequest, because the proxy
// may require re-authentication after responding to a 401 or
// to a redirect. If you don't, you can get into a
// 407-401-407-401- loop.
if( dwProxyAuthScheme != 0 )
bResults = WinHttpSetCredentials( hRequest,
WINHTTP_AUTH_TARGET_PROXY,
dwProxyAuthScheme,
pGetRequest->szProxyUsername,
pGetRequest->szProxyPassword,
NULL );
// Send a request.
bResults = WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0 );
// End the request.
if( bResults )
bResults = WinHttpReceiveResponse( hRequest, NULL );
// Resend the request in case of
// ERROR_WINHTTP_RESEND_REQUEST error.
if( !bResults && GetLastError( ) == ERROR_WINHTTP_RESEND_REQUEST)
continue;
// Check the status code.
if( bResults )
bResults = WinHttpQueryHeaders( hRequest,
WINHTTP_QUERY_STATUS_CODE |
WINHTTP_QUERY_FLAG_NUMBER,
NULL,
&dwStatusCode,
&dwSize,
NULL );
if( bResults )
{
switch( dwStatusCode )
{
case 200:
// The resource was successfully retrieved.
// You can use WinHttpReadData to read the
// contents of the server's response.
printf( "The resource was successfully retrieved.\n" );
bDone = TRUE;
break;
case 401:
// The server requires authentication.
printf(" The server requires authentication. Sending credentials...\n" );
// Obtain the supported and preferred schemes.
bResults = WinHttpQueryAuthSchemes( hRequest,
&dwSupportedSchemes,
&dwFirstScheme,
&dwTarget );
// Set the credentials before resending the request.
if( bResults )
{
dwSelectedScheme = ChooseAuthScheme( dwSupportedSchemes);
if( dwSelectedScheme == 0 )
bDone = TRUE;
else
bResults = WinHttpSetCredentials( hRequest,
dwTarget,
dwSelectedScheme,
pGetRequest->szServerUsername,
pGetRequest->szServerPassword,
NULL );
}
// If the same credentials are requested twice, abort the
// request. For simplicity, this sample does not check
// for a repeated sequence of status codes.
if( dwLastStatus == 401 )
bDone = TRUE;
break;
case 407:
// The proxy requires authentication.
printf( "The proxy requires authentication. Sending credentials...\n" );
// Obtain the supported and preferred schemes.
bResults = WinHttpQueryAuthSchemes( hRequest,
&dwSupportedSchemes,
&dwFirstScheme,
&dwTarget );
// Set the credentials before resending the request.
if( bResults )
dwProxyAuthScheme = ChooseAuthScheme(dwSupportedSchemes);
// If the same credentials are requested twice, abort the
// request. For simplicity, this sample does not check
// for a repeated sequence of status codes.
if( dwLastStatus == 407 )
bDone = TRUE;
break;
default:
// The status code does not indicate success.
printf("Error. Status code %d returned.\n", dwStatusCode);
bDone = TRUE;
}
}
// Keep track of the last status code.
dwLastStatus = dwStatusCode;
// If there are any errors, break out of the loop.
if( !bResults )
bDone = TRUE;
}
// Report any errors.
if( !bResults )
{
DWORD dwLastError = GetLastError( );
printf( "Error %d has occurred.\n", dwLastError );
}
// Close any open handles.
if( hRequest ) WinHttpCloseHandle( hRequest );
if( hConnect ) WinHttpCloseHandle( hConnect );
if( hSession ) WinHttpCloseHandle( hSession );
}
You just have to inject your WinHttpSetOption(WINHTTP_OPTION_PROXY) where appropriate, and be sure that you are handling authentication requests for both proxy and non-proxy connections (in case the target HTTP server requires its own authentication).
We have written a single threaded client based on the boost asio. The client needs to implement a timeout, so that the connection is broken if the read or write from server was not completed in a stipulated time period. But the async_wait for the deadline_timer does not kick off untill I don't call run for the io_service. Now if I call run on the io_service then my reading and writing to the server is not possible.
Please see the excerpts from my current code:
typedef boost::scoped_ptr<boost::asio::ip::tcp::socket> SocketPtr;
typedef boost::shared_ptr<boost::asio::deadline_timer> DLTPtr;
SocketPtr m_SocketPtrClient;
DLPtr m_ClientTimeoutDLTPtr;
boost::asio::io_service ios;
m_SocketPtrClient.reset( new boost::asio::ip::tcp::socket( ios));
m_ClientTimeoutDLTPtr.reset( new deadline_timer( ios));
m_ClientTimeoutDLTPtr->expires_from_now( boost::posix_time::seconds( m_uiCommTimeout));
m_ClientTimeoutDLTPtr->async_wait( boost::bind( &MyClass::clientTimeoutHandler,
this,
boost::asio::placeholders::error
)
);
m_SocketPtrClient->connect
(
boost::asio::ip::tcp::endpoint
(
boost::asio::ip::address::from_string
(
m_sCommAddress == "localhost" ? "127.0.0.1" : m_sCommAddress
), m_usCommPort
), ec
);
if( !ec && m_SocketPtrClient->is_open())
{
m_ClientTimeoutDLTPtr->cancel();
}
else
{
m_ClientTimeoutDLTPtr->cancel();
m_SocketPtrClient->close();
return eStateError;
}
//install a timeout handler
m_ClientTimeoutDLTPtr->expires_from_now( boost::posix_time::seconds( m_uiCommTimeout));
m_ClientTimeoutDLTPtr->async_wait( boost::bind( &MyClass::clientTimeoutHandler,
this,
boost::asio::placeholders::error
)
);
ec = writeToServer( *m_SocketPtrClient);
if( ec)
{
// do error handling and throw an exception
}
m_ClientTimeoutDLTPtr->cancel();
//install a timeout handler
m_ClientTimeoutDLTPtr->expires_from_now( boost::posix_time::seconds( m_uiCommTimeout));
m_ClientTimeoutDLTPtr->async_wait( boost::bind( &MyClass::clientTimeoutHandler,
this,
boost::asio::placeholders::error
)
);
ec = readFromServer( *m_SocketPtrClient);
if( ec)
{
// do error handling and throw an exception
}
m_ClientTimeoutDLTPtr->cancel();
void MyClass::clientTimeoutHandler( const boost::system::error_code& ec)
{
if( ec)
{
m_ClientTimeoutDLTPtr->cancel();
m_SocketPtrClient->close();
m_ssMsg << std::endl << "break all handling because of timeout on io_service of Client!";
}
else
{
m_ClientTimeoutDLTPtr->expires_from_now( boost::posix_time::seconds( m_uiCommTimeout));
m_ClientTimeoutDLTPtr->async_wait( boost::bind( &MyClass::clientTimeoutHandler,
this,
boost::asio::placeholders::error
)
);
}
}
I need to connect, write to the server and then get response from the server and for each operation I need the timeout to kickoff. If I call the run from io_service then I can't make my these three calls.
I need to connect, write to the server and then get response from the
server and for each operation I need the timeout to kickoff. If I call
the run from io_service then I can't make my these three calls.
When using deadline_timer::async_wait() you will need to use the corresponding asynchronous socket methods such as socket::async_connect() instead of socket::connect().
For some days now I've been battling with printing XPS to file without the dialog.
I've read posts on the matter in CodeGuru and by Feng Yuan (MSDN), along with many discussion topics here and I am still lost.
Specifically my scenario is that I have a 3rd party API that I must use, and it prints to the default printer (say Microsoft XPS Document Writer). I want to be able to "apply" a filename prior to the printing procedure, and of course not to have dialog.
I've tried working with WinDDK - XPSDRV and LOCALMON samples but wasn't able to figure out exactly how to manipulate the code to achieve my goals. (or even fully understand if I need a new printer driver or a new port type)
I ran into the same need. Following is some of the logic that provides the desired functionality for me:
//
// PrintDocument_inst
//
this.PrintDocument_inst.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.k_line_PrintPage);
private void Print( string align_file_name )
{
if ( plot_metafile == null )
{
MessageBox.Show( "you need to load offset data before printing a plot" );
return;
}
try
{
PrintDocument_inst.DefaultPageSettings = PageSettings_inst;
PrintDialog_inst = new PrintDialog( );
PrintDialog_inst.Document = PrintDocument_inst;
PrintDialog_inst.UseEXDialog = true; // this must be set true or dialog won't show on 64 bit Vista
PrintDialog_inst.PrinterSettings.PrinterName = "Microsoft XPS Document Writer";
PrintDialog_inst.PrinterSettings.PrintToFile = true;
PrintDialog_inst.PrinterSettings.PrintFileName = align_file_name;
i_page_to_print_next = 1;
n_pages_still_to_print = 1;
PrintDocument_inst.Print( );
}
catch ( Exception e )
{
MessageBox.Show( e.ToString( ) );
}
finally
{
}
} // end of function Print( string align_file_name )
//PrintPage event handler
private void k_line_PrintPage(object sender,PrintPageEventArgs ppea)
{
int leftMargin = ppea.MarginBounds.Left;
int topMargin = ppea.MarginBounds.Top ;
try
{
float _scale_f;
if ( PrintDialog_inst != null )
{
string str_printer_name = PrintDialog_inst.PrinterSettings.PrinterName.ToString ( );
if ( str_printer_name.CompareTo ( "Adobe PDF" ) == 0 )
{
_scale_f = 0.61F; // 0.85F;
}
else
{
_scale_f = 0.59F; // 0.82F;
}
}
else // case of print preview
{
_scale_f = 0.59F; // 0.82F;
}
if ( _scale_f != 1.0F ) ppea.Graphics.ScaleTransform ( _scale_f, _scale_f );
ppea.Graphics.DrawImage ( plot_metafile, leftMargin, topMargin );
ppea.HasMorePages = ( --n_pages_still_to_print > 0 ? true : false );
}
finally
{
}
} // end of private void k_line_PrintPage(object sender,PrintPageEventArgs ppea)
You will delete filters in pipeline xml and also related dll's in inf file. But yet, as I did, i guess you will face problem of printing canvas (graphics). I wasn't able to convert / transform this canvas to glyphs to get the contents of it.
If you had further issues, let me know
Kind Regards
I use VS6 and ATL with CServiceModule to implement a custom windows service. In case of a fatal error service should shut itself down. Since CServiceModule is available via _Module variable in all files I thought of something like this to cause CServiceModule::Run to stop pumping messages and shut itself down
PostThreadMessage(_Module.dwThreadID, WM_QUIT, 0, 0);
Is this correct or you have better idea ?
For self shutdown you send command to Service Manager. Try this sample :
BOOL StopServiceCmd ( const char * szServiceName )
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
SERVICE_STATUS ssStatus; // current status of the service
BOOL bRet;
int iCont=0;
schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager )
{
schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
if (schService)
{
// try to stop the service
if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
{
Sleep( 1000 );
while( QueryServiceStatus( schService, &ssStatus ) )
{
iCont++;
if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
{
Sleep( 1000 );
if ( iCont > 4 ) break;
}
else
break;
}
if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
bRet = TRUE;
else
bRet = FALSE;
}
CloseServiceHandle(schService);
}
else
bRet = FALSE;
CloseServiceHandle(schSCManager);
}
else
bRet = FALSE;
return bRet;
}
I believe that if you do this, then the service manager will think that your service has crashed and if the user ever sets it up to auto-restart, it will.
In .NET, you use the ServiceController to signal your service to shut down. I expect it is similar in Win32 since most of this stuff in .NET is just wrappers. Sorry, I don't have C++ code handy to shut down the service, but here is the .NET code. This will hopefully help you Google the info you need, or find the docs in MSDN.
This is from some test suite code, thus the style of error checking ;) You will need to put this code in a thread so that the shutdown message gets handled.
private void stopPLService( bool close )
{
if ( m_serviceController == null )
{
m_serviceController = new ServiceController( "PLService" );
}
WriteLine( "StopPLService" );
if ( m_serviceController != null )
{
try
{
m_serviceController.Stop();
}
catch
{
// Probably just means that it wasn't running or installed, ignore
}
// Wait up to 30 seconds for the service to stop
try
{
m_serviceController.WaitForStatus( ServiceControllerStatus.Stopped, new TimeSpan( 0, 0, 30 ) );
}
catch ( System.ServiceProcess.TimeoutException )
{
Assert.Fail( "Timeout waiting for PLService to stop" );
}
catch
{
// Not installed, we only care in the start
}
if ( close )
{
m_serviceController.Close();
m_serviceController = null;
}
}
}
You probably want to use the ControlService or ControlServiceEx methods to shutdown your service. You should be able to get the required handle from the CServiceModule.