Please see my other blog for Oracle EBusiness Suite Posts - EBMentors

Search This Blog

Note: All the posts are based on practical approach avoiding lengthy theory. All have been tested on some development servers. Please don’t test any post on production servers until you are sure.

Tuesday, June 26, 2012

Send Message to Users by OS Command using PL/SQL

From one of my client ,it was required to send the message to application users (on Windows) for specific events by the database server. I used  the simple msg (Win command) for this purpose , example given below :


Create the OSCommand Java Class
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "OSCommand" AS
import java.io.*;
public class OSCommand{
public static String Run(String Command){
try{
Runtime.getRuntime().exec(Command);
return("0");
}
catch (Exception e){
System.out.println("Error running command: " + Command +
"\n" + e.getMessage());
return(e.getMessage());
}
}
}

Create the Wrapper Function to use Java class
CREATE or REPLACE FUNCTION OSCommand_Run(Command IN STRING)
RETURN VARCHAR2 IS
LANGUAGE JAVA
NAME 'OSCommand.Run(java.lang.String) return int';

Connect as SYS or SYSTEM and grant the following privilege to the desired user
Execute dbms_java.grant_permission( 'SCOTT','SYS:java.io.FilePermission','<>','execute');
execute dbms_java.grant_permission( 'SCOTT','SYS:java.lang.RuntimePermission','writeFileDescriptor','*' );
execute dbms_java.grant_permission( 'SCOTT','SYS:java.lang.RuntimePermission','readFileDescriptor','*' );
commit;

Test it
Set Serverout On
Declare
x Varchar2(2000);
vCMD varchar2(100);
vUser varchar2(50);
vMsg varchar2(1000);
vWait integer := 10;
Begin
vCMD := 'cmd /c msg /TIME:'||vWait;
vUser := ' Inam ';
vMsg := 'Test Msg by PL/SQL';
x := OSCommand_Run(vCMD||vUser||vMsg);
DBMS_OUTPUT.Put_Line(x);
End;
/

Create procedure for your easiness, if you want

create or replace procedure proc_send_msg(pMsg varchar2)
is
    x Varchar2(2000);
    vCMD varchar2(100);
    vUser varchar2(50);
    vMsg varchar2(1000);
    vWait integer := 10;
Begin
    vCMD := 'cmd /c msg /TIME:'||vWait;
    vUser := ' Inam ';
    vMsg := pMsg;
    x := OSCommand_Run(vCMD||vUser||vMsg);
    DBMS_OUTPUT.Put_Line(x);

End;
/

Even you can schedule it if required
DECLARE
  X NUMBER;
BEGIN
  SYS.DBMS_JOB.SUBMIT
    (
      job        => X
     ,what       => 'FOR REC IN (select OSUSER,USERNAME,TERMINAL,MACHINE,STATUS,STATE,LAST_CALL_ET,
''Dear ''||OSUSER||'' You are inactive for the last half an hour'' msg
from v$session
where last_call_et > 1800) LOOP
proc_send_msg(msg);
END LOOP; '
     ,next_date  => to_date('06/26/2012 12:00:33','mm/dd/yyyy hh24:mi:ss')
     ,interval   => 'SYSDATE+2/1440 '
     ,no_parse   => FALSE
    );
:JobNumber := to_char(X);
END;
 /

Some sample msg command usage:
msg /SERVER:Inam-PC inam salam -- machine name then username and message
msg Inam "salam" -- username and message
msg Inam /TIME:10 "Salam" -- with message delay in seconds
msg /TIME:10 /SERVER:Inam-PC inam Salam

Note:
If you get any error (code) while running the msg command, you can check the error code as below
net helpmsg ERRORCODE
eg;net helpmsg 5

No comments: