Pages

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:

Post a Comment