B
BENI
Hi all,
i detail out an issue i am facing while trying to read messages from
outlook via a windows service.
The goal of the code is to scan outlook inbox every 10 minutes and if
any specified file attachment is found ... save it.
The code will be installed as an windows service and scan for the
email automatically.
The service code is fine and runs in background as well but as I call
outlook via win32ole from the service mainloop it does not give me
the inbox with any item.
Can any one lead me to the problem??
the service code
it works like a champ
================
require 'win32/service'
include Win32
puts 'VERSION: ' + Service::VERSION
SERVICE_NAME = 'Kpi-file-Scanner'
SERVICE_DISPLAYNAME = 'An-outlook-scanner'
cmd = 'c:\instantrails\ruby\bin\ruby'
cmd += '"C:\\instantrails\\rails_apps\\kpi\\vendor\\service\
\outlookpull.rb"'
raise ArgumentError, 'No argument provided' unless ARGV[0]
case ARGV[0].downcase
when 'install'
svc= Service.new(SERVICE_NAME, nil,{
:service_type => Service::WIN32_OWN_PROCESS,
:description => SERVICE_DISPLAYNAME,
:start_type => Service::AUTO_START,
:error_control => Service::ERROR_NORMAL,
:binary_path_name => cmd,
:load_order_group => 'Network',
:dependencies => ['W32Time','Schedule'],
:display_name => 'Kpi-file-Scanner'}
)
puts 'Service ' + SERVICE_NAME + ' installed'
when 'start'
if Service.status(SERVICE_NAME).current_state != 'running'
Service.start(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'running'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' started'
else
puts 'Already running'
end
when 'stop'
if Service.status(SERVICE_NAME).current_state != 'stopped'
Service.stop(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'stopped'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' stopped'
else
puts 'Already stopped'
end
when 'uninstall', 'delete'
if Service.status(SERVICE_NAME).current_state != 'stopped'
Service.stop(SERVICE_NAME)
end
while Service.status(SERVICE_NAME).current_state != 'stopped'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
Service.delete(SERVICE_NAME)
puts 'Service ' + SERVICE_NAME + ' deleted'
when 'pause'
if Service.status(SERVICE_NAME).current_state != 'paused'
Service.pause(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'paused'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' paused'
else
puts 'Already paused'
end
when 'resume'
if Service.status(SERVICE_NAME).current_state != 'running'
Service.resume(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'running'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' resumed'
else
puts 'Already running'
end
else
raise ArgumentError, 'unknown option: ' + ARGV[0]
end
==============================================
now the outlookpull.rb code that is called by this service
===================================================
LOG_FILE = "C:\\instantrails\\rails_apps\\kpi\\vendor\\service\
\test.log"
begin
require "C:\\instantrails\\ruby\\lib\\ruby\\gems\\1.8\\gems\
\actionpack-2.0.2\\lib\\action_controller.rb"
require "C:\\instantrails\\rails_apps\\kpi\\app\\controllers\
\application.rb"
require "C:\\instantrails\\rails_apps\\kpi\\app\\controllers\
\kpimumbai_controller.rb"
File.open(LOG_FILE, "a+"){ |f| f.puts "kpimumbai_controller.rb
required" }
require 'win32/service'
require 'win32/daemon'
include Win32
require 'win32ole'
require "parsedate.rb"
include ParseDate
class Daemon
def service_init
@a=KpimumbaiController.new
sleep 10
end
def service_main
msg = 'service_main entered at: ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
#@first_entry = true
while running?
if state == RUNNING
msg = 'running state entered at : ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
begin
#@tick.refresh(@first_entry,@sqlconnect)
#@first_entry = false
#require 'win32ole'
#we will get the time of the last parsed message and
#will go in only if the message timing is after that of
the last parsed
#message time
File.open(LOG_FILE, "a+"){ |f| f.puts "just before
readlines" }
last_time=IO.readlines("C:\\instantrails\\rails_apps
\\kpi\\vendor\\service\\spawntime.log")
last_time=last_time.to_s.chomp
File.open(LOG_FILE, "a+"){ |f| f.puts
"=====last_time:#{last_time}" }
if last_time.to_s == "nil"
last_time="1971/10/04 19:03:24"
end
@outlook = WIN32OLE.new('Outlook.Application')
@mapi = @outlook.GetNameSpace('MAPI')
@inbox = @mapi.GetDefaultFolder(6)
@file_c=1
arr_last_time =
parsedate(last_time.to_s).delete_if{|x|x=="nil"}
File.open(LOG_FILE, "a+"){ |f| f.puts
"=====arr_last_time:#{arr_last_time}" }
timed_last_time=Time.mktime(arr_last_time[0],arr_last_time[1],arr_last_time[2],arr_last_time[3],arr_last_time[4],arr_last_time[5])
File.open(LOG_FILE, "a+"){ |f| f.puts
"====timed_last_time:#{timed_last_time}" }
File.open(LOG_FILE, "a+"){ |f|
f.puts"#{@inbox.UnreadItemCount}:Unread Messages" }
File.open(LOG_FILE, "a+"){ |f| f.puts
"#{@inbox.Items.Count}: Messages" }
begin
@inbox.Items.each do |message|
File.open(LOG_FILE, "a+"){ |f| f.puts
"====mesage time:#{message.ReceivedTime}" }
time_of_the_message =
parsedate(message.ReceivedTime)
#this gives us the array containing the time
timed_time_of_the_message =
Time.mktime(time_of_the_message[0],time_of_the_message[1],time_of_the_message[2],time_of_the_message[3],time_of_the_message[4],time_of_the_message[5])
#we will compare this time with the last time
object and go in for looking
#onto attachment if this is newer
File.open(LOG_FILE, "a+"){ |f| f.puts
"time difference:#{timed_time_of_the_message-timed_last_time}"}
if timed_time_of_the_message >
timed_last_time
message.Attachments.each do |
attachment|
filepattern=attachment.fileName.to_s.index(/NBH_|BBH_/)
if filepattern !=
nil
File.open(LOG_FILE,
"a+"){ |f| f.puts "======#{attachment.fileName.to_s}"}
temp_filename = "C:\
\instantrails\\rails_apps\\kpi\\vendor\\service\\temp\
\#{attachment.FileName}"
Dir.foreach("C:\
\instantrails\\rails_apps\\kpi\\vendor\\service\\temp\\") { |x|
File.delete("C:\\instantrails\\rails_apps\\kpi\\vendor\\service\\temp\
\"+ x) if x!= "." && x!=".." }
attachment.SaveAsFile(temp_filename)
#we will now call
the fileupdater method of kpimumbaicontroller object
@a.fileupdateupdater(temp_filename)
@file_c +=1
end
end
else
next
end
timed_last_time=timed_time_of_the_message
end
rescue Exception => err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'the
error at inner begin: ' + err }
raise
end
msg = 'mailbox spawn succ at : ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
rescue Exception => err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'the
error at outer begin: ' + err }
#close @sqlconnection
raise
#msg = 'mail box spawn FAILED at : ' +
Time.now.to_s
#File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
#finally after every spawn we need to update the last time
stamp entry in the spawn file
File.open("C:\\instantrails\\rails_apps\\kpi\\vendor\
\service\\spawntime.log", "w+"){ |f| f.puts timed_last_time }
#outlook.close
sleep 180
else
msg = 'non running state entered at : ' +
Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
sleep 0.5
end
end
File.open(LOG_FILE, "a+"){ |f| f.puts "STATE: #{state}" }
msg = 'service_main left at: ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
def service_stop
msg = "Received stop signal at: " + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
def service_pause
msg = "Received pause signal at: " + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
def service_resume
msg = "Received resume signal at: " + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
end
svc=Daemon.new
svc.mainloop
rescue Exception => err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'Daemon failure: ' + err }
raise
end
==================================================
Sorry for a long code...
The problem is that my log file loooks like this
============================
kpimumbai_controller.rb required
service_main entered at: Tue Apr 08 17:30:24 +0530 2008
running state entered at : Tue Apr 08 17:30:24 +0530 2008
just before readlines
=====last_time:Mon Oct 04 19:03:24 +0530 1971
=====arr_last_time:197110419324+05301
====timed_last_time:Mon Oct 04 19:03:24 +0530 1971
0:Unread Messages
0: Messages
mailbox spawn succ at : Tue Apr 08 17:30:24 +0530 2008
===========================================
the inbox messagecount is returning 0 messages.
while if i run it without any service deamon via simple code like this
require 'win32ole'
outlook = WIN32OLE.new('Outlook.Application')
mapi = outlook.GetNameSpace('MAPI')
inbox = mapi.GetDefaultFolder(6)
file_c=1
#methods = []
#arrival_time=inbox.Items(1).ReceivedTime
#b=arrival_time.to_a
#puts arrival_time
#require "parsedate.rb"
#include ParseDate
#formatted_date=parsedate(arrival_time)
#p formatted_date
puts "#{inbox.UnreadItemCount}:so many unread messages"
puts "#{inbox.Items.Count}:so many messages"
=======================
i get output like a champ
===============
484:so many unread messages
11398:so many messages
========================
i am battling it out for last couple of days to find why.
and i need help badly.
Br
Rajib
i detail out an issue i am facing while trying to read messages from
outlook via a windows service.
The goal of the code is to scan outlook inbox every 10 minutes and if
any specified file attachment is found ... save it.
The code will be installed as an windows service and scan for the
email automatically.
The service code is fine and runs in background as well but as I call
outlook via win32ole from the service mainloop it does not give me
the inbox with any item.
Can any one lead me to the problem??
the service code
it works like a champ
================
require 'win32/service'
include Win32
puts 'VERSION: ' + Service::VERSION
SERVICE_NAME = 'Kpi-file-Scanner'
SERVICE_DISPLAYNAME = 'An-outlook-scanner'
cmd = 'c:\instantrails\ruby\bin\ruby'
cmd += '"C:\\instantrails\\rails_apps\\kpi\\vendor\\service\
\outlookpull.rb"'
raise ArgumentError, 'No argument provided' unless ARGV[0]
case ARGV[0].downcase
when 'install'
svc= Service.new(SERVICE_NAME, nil,{
:service_type => Service::WIN32_OWN_PROCESS,
:description => SERVICE_DISPLAYNAME,
:start_type => Service::AUTO_START,
:error_control => Service::ERROR_NORMAL,
:binary_path_name => cmd,
:load_order_group => 'Network',
:dependencies => ['W32Time','Schedule'],
:display_name => 'Kpi-file-Scanner'}
)
puts 'Service ' + SERVICE_NAME + ' installed'
when 'start'
if Service.status(SERVICE_NAME).current_state != 'running'
Service.start(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'running'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' started'
else
puts 'Already running'
end
when 'stop'
if Service.status(SERVICE_NAME).current_state != 'stopped'
Service.stop(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'stopped'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' stopped'
else
puts 'Already stopped'
end
when 'uninstall', 'delete'
if Service.status(SERVICE_NAME).current_state != 'stopped'
Service.stop(SERVICE_NAME)
end
while Service.status(SERVICE_NAME).current_state != 'stopped'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
Service.delete(SERVICE_NAME)
puts 'Service ' + SERVICE_NAME + ' deleted'
when 'pause'
if Service.status(SERVICE_NAME).current_state != 'paused'
Service.pause(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'paused'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' paused'
else
puts 'Already paused'
end
when 'resume'
if Service.status(SERVICE_NAME).current_state != 'running'
Service.resume(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'running'
puts 'One moment...' +
Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' resumed'
else
puts 'Already running'
end
else
raise ArgumentError, 'unknown option: ' + ARGV[0]
end
==============================================
now the outlookpull.rb code that is called by this service
===================================================
LOG_FILE = "C:\\instantrails\\rails_apps\\kpi\\vendor\\service\
\test.log"
begin
require "C:\\instantrails\\ruby\\lib\\ruby\\gems\\1.8\\gems\
\actionpack-2.0.2\\lib\\action_controller.rb"
require "C:\\instantrails\\rails_apps\\kpi\\app\\controllers\
\application.rb"
require "C:\\instantrails\\rails_apps\\kpi\\app\\controllers\
\kpimumbai_controller.rb"
File.open(LOG_FILE, "a+"){ |f| f.puts "kpimumbai_controller.rb
required" }
require 'win32/service'
require 'win32/daemon'
include Win32
require 'win32ole'
require "parsedate.rb"
include ParseDate
class Daemon
def service_init
@a=KpimumbaiController.new
sleep 10
end
def service_main
msg = 'service_main entered at: ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
#@first_entry = true
while running?
if state == RUNNING
msg = 'running state entered at : ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
begin
#@tick.refresh(@first_entry,@sqlconnect)
#@first_entry = false
#require 'win32ole'
#we will get the time of the last parsed message and
#will go in only if the message timing is after that of
the last parsed
#message time
File.open(LOG_FILE, "a+"){ |f| f.puts "just before
readlines" }
last_time=IO.readlines("C:\\instantrails\\rails_apps
\\kpi\\vendor\\service\\spawntime.log")
last_time=last_time.to_s.chomp
File.open(LOG_FILE, "a+"){ |f| f.puts
"=====last_time:#{last_time}" }
if last_time.to_s == "nil"
last_time="1971/10/04 19:03:24"
end
@outlook = WIN32OLE.new('Outlook.Application')
@mapi = @outlook.GetNameSpace('MAPI')
@inbox = @mapi.GetDefaultFolder(6)
@file_c=1
arr_last_time =
parsedate(last_time.to_s).delete_if{|x|x=="nil"}
File.open(LOG_FILE, "a+"){ |f| f.puts
"=====arr_last_time:#{arr_last_time}" }
timed_last_time=Time.mktime(arr_last_time[0],arr_last_time[1],arr_last_time[2],arr_last_time[3],arr_last_time[4],arr_last_time[5])
File.open(LOG_FILE, "a+"){ |f| f.puts
"====timed_last_time:#{timed_last_time}" }
File.open(LOG_FILE, "a+"){ |f|
f.puts"#{@inbox.UnreadItemCount}:Unread Messages" }
File.open(LOG_FILE, "a+"){ |f| f.puts
"#{@inbox.Items.Count}: Messages" }
begin
@inbox.Items.each do |message|
File.open(LOG_FILE, "a+"){ |f| f.puts
"====mesage time:#{message.ReceivedTime}" }
time_of_the_message =
parsedate(message.ReceivedTime)
#this gives us the array containing the time
timed_time_of_the_message =
Time.mktime(time_of_the_message[0],time_of_the_message[1],time_of_the_message[2],time_of_the_message[3],time_of_the_message[4],time_of_the_message[5])
#we will compare this time with the last time
object and go in for looking
#onto attachment if this is newer
File.open(LOG_FILE, "a+"){ |f| f.puts
"time difference:#{timed_time_of_the_message-timed_last_time}"}
if timed_time_of_the_message >
timed_last_time
message.Attachments.each do |
attachment|
filepattern=attachment.fileName.to_s.index(/NBH_|BBH_/)
if filepattern !=
nil
File.open(LOG_FILE,
"a+"){ |f| f.puts "======#{attachment.fileName.to_s}"}
temp_filename = "C:\
\instantrails\\rails_apps\\kpi\\vendor\\service\\temp\
\#{attachment.FileName}"
Dir.foreach("C:\
\instantrails\\rails_apps\\kpi\\vendor\\service\\temp\\") { |x|
File.delete("C:\\instantrails\\rails_apps\\kpi\\vendor\\service\\temp\
\"+ x) if x!= "." && x!=".." }
attachment.SaveAsFile(temp_filename)
#we will now call
the fileupdater method of kpimumbaicontroller object
@a.fileupdateupdater(temp_filename)
@file_c +=1
end
end
else
next
end
timed_last_time=timed_time_of_the_message
end
rescue Exception => err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'the
error at inner begin: ' + err }
raise
end
msg = 'mailbox spawn succ at : ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
rescue Exception => err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'the
error at outer begin: ' + err }
#close @sqlconnection
raise
#msg = 'mail box spawn FAILED at : ' +
Time.now.to_s
#File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
#finally after every spawn we need to update the last time
stamp entry in the spawn file
File.open("C:\\instantrails\\rails_apps\\kpi\\vendor\
\service\\spawntime.log", "w+"){ |f| f.puts timed_last_time }
#outlook.close
sleep 180
else
msg = 'non running state entered at : ' +
Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
sleep 0.5
end
end
File.open(LOG_FILE, "a+"){ |f| f.puts "STATE: #{state}" }
msg = 'service_main left at: ' + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
def service_stop
msg = "Received stop signal at: " + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
def service_pause
msg = "Received pause signal at: " + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
def service_resume
msg = "Received resume signal at: " + Time.now.to_s
File.open(LOG_FILE, "a+"){ |f| f.puts msg }
end
end
svc=Daemon.new
svc.mainloop
rescue Exception => err
File.open(LOG_FILE, "a+"){ |fh| fh.puts 'Daemon failure: ' + err }
raise
end
==================================================
Sorry for a long code...
The problem is that my log file loooks like this
============================
kpimumbai_controller.rb required
service_main entered at: Tue Apr 08 17:30:24 +0530 2008
running state entered at : Tue Apr 08 17:30:24 +0530 2008
just before readlines
=====last_time:Mon Oct 04 19:03:24 +0530 1971
=====arr_last_time:197110419324+05301
====timed_last_time:Mon Oct 04 19:03:24 +0530 1971
0:Unread Messages
0: Messages
mailbox spawn succ at : Tue Apr 08 17:30:24 +0530 2008
===========================================
the inbox messagecount is returning 0 messages.
while if i run it without any service deamon via simple code like this
require 'win32ole'
outlook = WIN32OLE.new('Outlook.Application')
mapi = outlook.GetNameSpace('MAPI')
inbox = mapi.GetDefaultFolder(6)
file_c=1
#methods = []
#arrival_time=inbox.Items(1).ReceivedTime
#b=arrival_time.to_a
#puts arrival_time
#require "parsedate.rb"
#include ParseDate
#formatted_date=parsedate(arrival_time)
#p formatted_date
puts "#{inbox.UnreadItemCount}:so many unread messages"
puts "#{inbox.Items.Count}:so many messages"
=======================
i get output like a champ
===============
484:so many unread messages
11398:so many messages
========================
i am battling it out for last couple of days to find why.
and i need help badly.
Br
Rajib