From: BENI Date: 2008-04-08T22:50:08+09:00 Subject: outlook and win32 service 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